#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <sstream>
#include "BLEAdvertisedDevice.h"
#include "BLEUtils.h"
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
static const char* LOG_TAG="BLEAdvertisedDevice";
BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_adFlag = 0;
m_appearance = 0;
m_deviceType = 0;
m_manufacturerData = "";
m_name = "";
m_rssi = -9999;
m_serviceData = "";
m_txPower = 0;
m_pScan = nullptr;
m_haveAppearance = false;
m_haveManufacturerData = false;
m_haveName = false;
m_haveRSSI = false;
m_haveServiceData = false;
m_haveServiceUUID = false;
m_haveTXPower = false;
}
BLEAddress BLEAdvertisedDevice::getAddress() {
return m_address;
}
uint16_t BLEAdvertisedDevice::getAppearance() {
return m_appearance;
}
std::string BLEAdvertisedDevice::getManufacturerData() {
return m_manufacturerData;
}
std::string BLEAdvertisedDevice::getName() {
return m_name;
}
int BLEAdvertisedDevice::getRSSI() {
return m_rssi;
}
BLEScan* BLEAdvertisedDevice::getScan() {
return m_pScan;
}
std::string BLEAdvertisedDevice::getServiceData() {
return m_serviceData;
}
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
return m_serviceDataUUID;
}
BLEUUID BLEAdvertisedDevice::getServiceUUID() {
return m_serviceUUIDs[0];
}
bool BLEAdvertisedDevice::isAdvertisingService(BLEUUID uuid){
for (int i = 0; i < m_serviceUUIDs.size(); ++i) {
if(m_serviceUUIDs[i].equals(uuid))
return true;
}
return false;
}
int8_t BLEAdvertisedDevice::getTXPower() {
return m_txPower;
}
bool BLEAdvertisedDevice::haveAppearance() {
return m_haveAppearance;
}
bool BLEAdvertisedDevice::haveManufacturerData() {
return m_haveManufacturerData;
}
bool BLEAdvertisedDevice::haveName() {
return m_haveName;
}
bool BLEAdvertisedDevice::haveRSSI() {
return m_haveRSSI;
}
bool BLEAdvertisedDevice::haveServiceData() {
return m_haveServiceData;
}
bool BLEAdvertisedDevice::haveServiceUUID() {
return m_haveServiceUUID;
}
bool BLEAdvertisedDevice::haveTXPower() {
return m_haveTXPower;
}
void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) {
uint8_t length;
uint8_t ad_type;
uint8_t sizeConsumed = 0;
bool finished = false;
while(!finished) {
length = *payload;
payload++;
sizeConsumed += 1 + length;
if (length != 0) {
ad_type = *payload;
payload++;
length--;
char* pHex = BLEUtils::buildHexData(nullptr, payload, length);
ESP_LOGD(LOG_TAG, "Type: 0x%.2x (%s), length: %d, data: %s",
ad_type, BLEUtils::advTypeToString(ad_type), length, pHex);
free(pHex);
switch(ad_type) {
case ESP_BLE_AD_TYPE_NAME_CMPL: {
setName(std::string(reinterpret_cast<char*>(payload), length));
break;
}
case ESP_BLE_AD_TYPE_TX_PWR: {
setTXPower(*payload);
break;
}
case ESP_BLE_AD_TYPE_APPEARANCE: {
setAppearance(*reinterpret_cast<uint16_t*>(payload));
break;
}
case ESP_BLE_AD_TYPE_FLAG: {
setAdFlag(*payload);
break;
}
case ESP_BLE_AD_TYPE_16SRV_CMPL:
case ESP_BLE_AD_TYPE_16SRV_PART: {
for (int var = 0; var < length/2; ++var) {
setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload+var*2)));
}
break;
}
case ESP_BLE_AD_TYPE_32SRV_CMPL:
case ESP_BLE_AD_TYPE_32SRV_PART: {
for (int var = 0; var < length/4; ++var) {
setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload+var*4)));
}
break;
}
case ESP_BLE_AD_TYPE_128SRV_CMPL: {
setServiceUUID(BLEUUID(payload, 16, false));
break;
}
case ESP_BLE_AD_TYPE_128SRV_PART: {
setServiceUUID(BLEUUID(payload, 16, false));
break;
}
case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE: {
setManufacturerData(std::string(reinterpret_cast<char*>(payload), length));
break;
}
case ESP_BLE_AD_TYPE_SERVICE_DATA: {
if (length < 2) {
ESP_LOGE(LOG_TAG, "Length too small for ESP_BLE_AD_TYPE_SERVICE_DATA");
break;
}
uint16_t uuid = *(uint16_t *)payload;
setServiceDataUUID(BLEUUID(uuid));
if (length > 2) {
setServiceData(std::string(reinterpret_cast<char*>(payload+2), length-2));
}
break;
}
case ESP_BLE_AD_TYPE_32SERVICE_DATA: {
if (length < 4) {
ESP_LOGE(LOG_TAG, "Length too small for ESP_BLE_AD_TYPE_32SERVICE_DATA");
break;
}
uint32_t uuid = *(uint32_t *)payload;
setServiceDataUUID(BLEUUID(uuid));
if (length > 4) {
setServiceData(std::string(reinterpret_cast<char*>(payload+4), length-4));
}
break;
}
case ESP_BLE_AD_TYPE_128SERVICE_DATA: {
if (length < 16) {
ESP_LOGE(LOG_TAG, "Length too small for ESP_BLE_AD_TYPE_128SERVICE_DATA");
break;
}
setServiceDataUUID(BLEUUID(payload, (size_t)16, false));
if (length > 16) {
setServiceData(std::string(reinterpret_cast<char*>(payload+16), length-16));
}
break;
}
default: {
ESP_LOGD(LOG_TAG, "Unhandled type: adType: %d - 0x%.2x", ad_type, ad_type);
break;
}
}
payload += length;
}
if (sizeConsumed >=31 || length == 0) {
finished = true;
}
}
}
void BLEAdvertisedDevice::setAddress(BLEAddress address) {
m_address = address;
}
void BLEAdvertisedDevice::setAdFlag(uint8_t adFlag) {
m_adFlag = adFlag;
}
void BLEAdvertisedDevice::setAppearance(uint16_t appearance) {
m_appearance = appearance;
m_haveAppearance = true;
ESP_LOGD(LOG_TAG, "- appearance: %d", m_appearance);
}
void BLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
m_manufacturerData = manufacturerData;
m_haveManufacturerData = true;
char* pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)m_manufacturerData.data(), (uint8_t)m_manufacturerData.length());
ESP_LOGD(LOG_TAG, "- manufacturer data: %s", pHex);
free(pHex);
}
void BLEAdvertisedDevice::setName(std::string name) {
m_name = name;
m_haveName = true;
ESP_LOGD(LOG_TAG, "- setName(): name: %s", m_name.c_str());
}
void BLEAdvertisedDevice::setRSSI(int rssi) {
m_rssi = rssi;
m_haveRSSI = true;
ESP_LOGD(LOG_TAG, "- setRSSI(): rssi: %d", m_rssi);
}
void BLEAdvertisedDevice::setScan(BLEScan* pScan) {
m_pScan = pScan;
}
void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
return setServiceUUID(BLEUUID(serviceUUID));
}
void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
m_serviceUUIDs.push_back(serviceUUID);
m_haveServiceUUID = true;
ESP_LOGD(LOG_TAG, "- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
}
void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
m_haveServiceData = true;
m_serviceData = serviceData;
}
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
m_haveServiceData = true;
m_serviceDataUUID = uuid;
}
void BLEAdvertisedDevice::setTXPower(int8_t txPower) {
m_txPower = txPower;
m_haveTXPower = true;
ESP_LOGD(LOG_TAG, "- txPower: %d", m_txPower);
}
std::string BLEAdvertisedDevice::toString() {
std::stringstream ss;
ss << "Name: " << getName() << ", Address: " << getAddress().toString();
if (haveAppearance()) {
ss << ", appearance: " << getAppearance();
}
if (haveManufacturerData()) {
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
ss << ", manufacturer data: " << pHex;
free(pHex);
}
if (haveServiceUUID()) {
ss << ", serviceUUID: " << getServiceUUID().toString();
}
if (haveTXPower()) {
ss << ", txPower: " << (int)getTXPower();
}
return ss.str();
}
#endif