Add complementary methods to NimBLEAdvertising and NimBLEAdvertisementData

Previous to this NimBLEAdvertising did not have some functionality that was in NimBLEAdvertisementData.
Also NimBLEAdvertisementData was missing functionality that exists in NimBLEAdvertising.

This resolves that by adding the missing functions to both classes.

Changed:
NimBLEAdvertising: Transmission power is no longer advertised by default and can be added to the advertisement by calling ::addTxPower()

Added:
- NimBLEAdvertising::setName
- NimBLEAdvertising::setManufacturerData
- NimBLEAdvertising::setURI
- NimBLEAdvertising::setServiceData
- NimBLEAdvertising::addTxPower
- NimBLEAdvertising::reset

- NimBLEAdvertisementData::addTxPower
- NimBLEAdvertisementData::setPreferredParams
- NimBLEAdvertisementData::setURI
This commit is contained in:
h2zero 2021-02-07 20:33:57 -07:00
parent 6e104dfb45
commit dff5122ce2
2 changed files with 187 additions and 23 deletions

View file

@ -32,23 +32,27 @@ static const char* LOG_TAG = "NimBLEAdvertising";
/** /**
* @brief Construct a default advertising object. * @brief Construct a default advertising object.
*/ */
NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() { NimBLEAdvertising::NimBLEAdvertising() {
reset();
} // NimBLEAdvertising
/**
* @brief Stops the current advertising and resets the advertising data to the default values.
*/
void NimBLEAdvertising::reset() {
stop();
memset(&m_advData, 0, sizeof m_advData); memset(&m_advData, 0, sizeof m_advData);
memset(&m_scanData, 0, sizeof m_scanData); memset(&m_scanData, 0, sizeof m_scanData);
memset(&m_advParams, 0, sizeof m_advParams); memset(&m_advParams, 0, sizeof m_advParams);
memset(&m_slaveItvl, 0, sizeof m_slaveItvl);
const char *name = ble_svc_gap_device_name(); const char *name = ble_svc_gap_device_name();
m_advData.name = (uint8_t *)name; m_advData.name = (uint8_t *)name;
m_advData.name_len = strlen(name); m_advData.name_len = strlen(name);
m_advData.name_is_complete = 1; m_advData.name_is_complete = 1;
m_advData.tx_pwr_lvl_is_present = 1;
m_advData.tx_pwr_lvl = NimBLEDevice::getPower(); m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP); m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
m_advData.appearance = 0;
m_advData.appearance_is_present = 0;
m_advData.mfg_data_len = 0;
m_advData.mfg_data = nullptr;
m_advData.slave_itvl_range = nullptr;
#if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON; m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
@ -56,17 +60,13 @@ NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() {
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND; m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
#endif #endif
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN; m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
m_advParams.itvl_min = 0;
m_advParams.itvl_max = 0;
m_customAdvData = false; m_customAdvData = false;
m_customScanResponseData = false; m_customScanResponseData = false;
m_scanResp = true; m_scanResp = true;
m_advDataSet = false; m_advDataSet = false;
// Set this to non-zero to prevent auto start if host reset before started by app. // Set this to non-zero to prevent auto start if host reset before started by app.
m_duration = BLE_HS_FOREVER; m_duration = BLE_HS_FOREVER;
} // reset
} // NimBLEAdvertising
/** /**
@ -85,6 +85,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
*/ */
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) { void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
addServiceUUID(NimBLEUUID(serviceUUID)); addServiceUUID(NimBLEUUID(serviceUUID));
m_advDataSet = false;
} // addServiceUUID } // addServiceUUID
@ -112,9 +113,95 @@ void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
void NimBLEAdvertising::setAppearance(uint16_t appearance) { void NimBLEAdvertising::setAppearance(uint16_t appearance) {
m_advData.appearance = appearance; m_advData.appearance = appearance;
m_advData.appearance_is_present = 1; m_advData.appearance_is_present = 1;
m_advDataSet = false;
} // setAppearance } // setAppearance
/**
* @brief Add the transmission power level to the advertisement packet.
*/
void NimBLEAdvertising::addTxPower() {
m_advData.tx_pwr_lvl_is_present = 1;
m_advDataSet = false;
} // addTxPower
/**
* @brief Set the advertised name of the device.
* @param [in] name The name to advertise.
*/
void NimBLEAdvertising::setName(const std::string &name) {
m_name.assign(name.begin(), name.end());
m_advData.name = &m_name[0];
m_advData.name_len = m_name.size();
m_advDataSet = false;
} // setName
/**
* @brief Set the advertised manufacturer data.
* @param [in] name The data to advertise.
*/
void NimBLEAdvertising::setManufacturerData(const std::string &data) {
m_mfgData.assign(data.begin(), data.end());
m_advData.mfg_data = &m_mfgData[0];
m_advData.mfg_data_len = m_mfgData.size();
m_advDataSet = false;
} // setManufacturerData
/**
* @brief Set the advertised URI.
* @param [in] name The URI to advertise.
*/
void NimBLEAdvertising::setURI(const std::string &uri) {
m_uri.assign(uri.begin(), uri.end());
m_advData.uri = &m_uri[0];
m_advData.uri_len = m_uri.size();
m_advDataSet = false;
} // setURI
/**
* @brief Set the service data advertised for the UUID.
* @param [in] uuid The UUID the service data belongs to.
* @param [in] data The data to advertise.
* @note If data length is 0 the service data will not be advertised.
*/
void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
switch (uuid.bitSize()) {
case 16: {
m_svcData16.assign((uint8_t*)&uuid.getNative()->u16.value, (uint8_t*)&uuid.getNative()->u16.value + 2);
m_svcData16.insert(m_svcData16.end(), data.begin(), data.end());
m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0];
m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0;
break;
}
case 32: {
m_svcData32.assign((uint8_t*)&uuid.getNative()->u32.value, (uint8_t*)&uuid.getNative()->u32.value + 4);
m_svcData32.insert(m_svcData32.end(), data.begin(), data.end());
m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0];
m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0;
break;
}
case 128: {
m_svcData128.assign(uuid.getNative()->u128.value, uuid.getNative()->u128.value + 16);
m_svcData128.insert(m_svcData128.end(), data.begin(), data.end());
m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0];
m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0;
break;
}
default:
return;
}
m_advDataSet = false;
} // setServiceData
/** /**
* @brief Set the type of advertisment to use. * @brief Set the type of advertisment to use.
* @param [in] adv_type: * @param [in] adv_type:
@ -172,6 +259,8 @@ void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
m_slaveItvl[2] = m_slaveItvl[0]; m_slaveItvl[2] = m_slaveItvl[0];
m_slaveItvl[3] = m_slaveItvl[1]; m_slaveItvl[3] = m_slaveItvl[1];
} }
m_advDataSet = false;
} // setMinPreferred } // setMinPreferred
@ -200,6 +289,8 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
m_slaveItvl[0] = m_slaveItvl[2]; m_slaveItvl[0] = m_slaveItvl[2];
m_slaveItvl[1] = m_slaveItvl[3]; m_slaveItvl[1] = m_slaveItvl[3];
} }
m_advDataSet = false;
} // setMaxPreferred } // setMaxPreferred
@ -209,6 +300,7 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
*/ */
void NimBLEAdvertising::setScanResponse(bool set) { void NimBLEAdvertising::setScanResponse(bool set) {
m_scanResp = set; m_scanResp = set;
m_advDataSet = false;
} // setScanResponse } // setScanResponse
@ -344,12 +436,29 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
if (!m_customAdvData && !m_advDataSet) { if (!m_customAdvData && !m_advDataSet) {
//start with 3 bytes for the flags data //start with 3 bytes for the flags data
uint8_t payloadLen = (2 + 1); uint8_t payloadLen = (2 + 1);
if(m_advData.mfg_data_len > 0)
payloadLen += (2 + m_advData.mfg_data_len);
if(m_advData.svc_data_uuid16_len > 0)
payloadLen += (2 + m_advData.svc_data_uuid16_len);
if(m_advData.svc_data_uuid32_len > 0)
payloadLen += (2 + m_advData.svc_data_uuid32_len);
if(m_advData.svc_data_uuid128_len > 0)
payloadLen += (2 + m_advData.svc_data_uuid128_len);
if(m_advData.uri_len > 0)
payloadLen += (2 + m_advData.uri_len);
if(m_advData.appearance_is_present) if(m_advData.appearance_is_present)
payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN); payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN);
if(m_advData.tx_pwr_lvl_is_present) if(m_advData.tx_pwr_lvl_is_present)
payloadLen += (2 + 1); payloadLen += (2 + BLE_HS_ADV_TX_PWR_LVL_LEN);
if(m_advData.slave_itvl_range != nullptr) if(m_advData.slave_itvl_range != nullptr)
payloadLen += (2 + 4); payloadLen += (2 + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
for(auto &it : m_serviceUUIDs) { for(auto &it : m_serviceUUIDs) {
if(it.getNative()->u.type == BLE_UUID_TYPE_16) { if(it.getNative()->u.type == BLE_UUID_TYPE_16) {
@ -433,7 +542,6 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
m_advData.name_is_complete = 0; m_advData.name_is_complete = 0;
} else { } else {
if(m_advData.tx_pwr_lvl_is_present) { if(m_advData.tx_pwr_lvl_is_present) {
m_advData.tx_pwr_lvl = 0;
m_advData.tx_pwr_lvl_is_present = 0; m_advData.tx_pwr_lvl_is_present = 0;
payloadLen -= (2 + 1); payloadLen -= (2 + 1);
} }
@ -581,7 +689,7 @@ void NimBLEAdvertising::advCompleteCB() {
if(m_advCompCB != nullptr) { if(m_advCompCB != nullptr) {
m_advCompCB(this); m_advCompCB(this);
} }
} } // advCompleteCB
/** /**
@ -590,7 +698,7 @@ void NimBLEAdvertising::advCompleteCB() {
*/ */
bool NimBLEAdvertising::isAdvertising() { bool NimBLEAdvertising::isAdvertising() {
return ble_gap_adv_active(); return ble_gap_adv_active();
} } // isAdvertising
/* /*
@ -608,7 +716,7 @@ void NimBLEAdvertising::onHostSync() {
// Otherwise we should tell the app that advertising stopped. // Otherwise we should tell the app that advertising stopped.
advCompleteCB(); advCompleteCB();
} }
} } // onHostSync
/** /**
@ -706,6 +814,18 @@ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
} // setManufacturerData } // setManufacturerData
/**
* @brief Set the URI to advertise.
* @param [in] uri The uri to advertise.
*/
void NimBLEAdvertisementData::setURI(const std::string &uri) {
char cdata[2];
cdata[0] = uri.length() + 1;
cdata[1] = BLE_HS_ADV_TYPE_URI;
addData(std::string(cdata, 2) + uri);
} // setURI
/** /**
* @brief Set the complete name of this device. * @brief Set the complete name of this device.
* @param [in] name The name to advertise. * @param [in] name The name to advertise.
@ -733,7 +853,7 @@ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
*/ */
void NimBLEAdvertisementData::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) { void NimBLEAdvertisementData::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) {
setServices(true, 16, v_uuid); setServices(true, 16, v_uuid);
} } // setCompleteServices16
/** /**
@ -742,7 +862,7 @@ void NimBLEAdvertisementData::setCompleteServices16(const std::vector<NimBLEUUID
*/ */
void NimBLEAdvertisementData::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) { void NimBLEAdvertisementData::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) {
setServices(true, 32, v_uuid); setServices(true, 32, v_uuid);
} } // setCompleteServices32
/** /**
@ -760,7 +880,7 @@ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
*/ */
void NimBLEAdvertisementData::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) { void NimBLEAdvertisementData::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) {
setServices(false, 16, v_uuid); setServices(false, 16, v_uuid);
} } // setPartialServices16
/** /**
@ -769,7 +889,7 @@ void NimBLEAdvertisementData::setPartialServices16(const std::vector<NimBLEUUID>
*/ */
void NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) { void NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) {
setServices(false, 32, v_uuid); setServices(false, 32, v_uuid);
} } // setPartialServices32
/** /**
@ -821,7 +941,7 @@ void NimBLEAdvertisementData::setServices(const bool complete, const uint8_t siz
} }
addData(std::string(cdata, 2) + uuids); addData(std::string(cdata, 2) + uuids);
} } // setServices
/** /**
@ -874,6 +994,35 @@ void NimBLEAdvertisementData::setShortName(const std::string &name) {
} // setShortName } // setShortName
/**
* @brief Adds Tx power level to the advertisement data.
*/
void NimBLEAdvertisementData::addTxPower() {
char cdata[3];
cdata[0] = BLE_HS_ADV_TX_PWR_LVL_LEN + 1;
cdata[1] = BLE_HS_ADV_TYPE_TX_PWR_LVL;
cdata[2] = NimBLEDevice::getPower();
addData(cdata, 3);
} // addTxPower
/**
* @brief Set the preferred connection interval parameters.
* @param [in] min The minimum interval desired.
* @param [in] max The maximum interval desired.
*/
void NimBLEAdvertisementData::setPreferredParams(uint16_t min, uint16_t max) {
char cdata[6];
cdata[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
cdata[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
cdata[2] = min;
cdata[3] = min >> 8;
cdata[4] = max;
cdata[5] = max >> 8;
addData(cdata, 6);
} // setPreferredParams
/** /**
* @brief Retrieve the payload that is to be advertised. * @brief Retrieve the payload that is to be advertised.
* @return The payload that is to be advertised. * @return The payload that is to be advertised.

View file

@ -54,6 +54,7 @@ public:
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid); void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
void setFlags(uint8_t); void setFlags(uint8_t);
void setManufacturerData(const std::string &data); void setManufacturerData(const std::string &data);
void setURI(const std::string &uri);
void setName(const std::string &name); void setName(const std::string &name);
void setPartialServices(const NimBLEUUID &uuid); void setPartialServices(const NimBLEUUID &uuid);
void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid); void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid);
@ -62,6 +63,8 @@ public:
void setShortName(const std::string &name); void setShortName(const std::string &name);
void addData(const std::string &data); // Add data to the payload. void addData(const std::string &data); // Add data to the payload.
void addData(char * data, size_t length); void addData(char * data, size_t length);
void addTxPower();
void setPreferredParams(uint16_t min, uint16_t max);
std::string getPayload(); // Retrieve the current advert payload. std::string getPayload(); // Retrieve the current advert payload.
private: private:
@ -86,6 +89,10 @@ public:
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr); bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
void stop(); void stop();
void setAppearance(uint16_t appearance); void setAppearance(uint16_t appearance);
void setName(const std::string &name);
void setManufacturerData(const std::string &data);
void setURI(const std::string &uri);
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
void setAdvertisementType(uint8_t adv_type); void setAdvertisementType(uint8_t adv_type);
void setMaxInterval(uint16_t maxinterval); void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval); void setMinInterval(uint16_t mininterval);
@ -95,6 +102,8 @@ public:
void setScanResponse(bool); void setScanResponse(bool);
void setMinPreferred(uint16_t); void setMinPreferred(uint16_t);
void setMaxPreferred(uint16_t); void setMaxPreferred(uint16_t);
void addTxPower();
void reset();
void advCompleteCB(); void advCompleteCB();
bool isAdvertising(); bool isAdvertising();
@ -115,6 +124,12 @@ private:
void (*m_advCompCB)(NimBLEAdvertising *pAdv); void (*m_advCompCB)(NimBLEAdvertising *pAdv);
uint8_t m_slaveItvl[4]; uint8_t m_slaveItvl[4];
uint32_t m_duration; uint32_t m_duration;
std::vector<uint8_t> m_svcData16;
std::vector<uint8_t> m_svcData32;
std::vector<uint8_t> m_svcData128;
std::vector<uint8_t> m_name;
std::vector<uint8_t> m_mfgData;
std::vector<uint8_t> m_uri;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)