Read data from an ibeacon ? [ SOLVED ]

I have a Tilt hydrometer that acts as a beacon and transmits Temperature and specific gravity.
I installed the ESP32 board in the Arduino IDE.
I loaded the sketch BLE_scan from the ESP32 BLE Arduino examples .
The hydrometer is perfectly detected:

Address

F7:44:3E:01:7F:36

ManufacturerData

4C 00 02 15 A4 95 BB 20 C5 B1 4B 44 B5 12 13 70 F0 2D 74 DE 00 4A 03 F1 22

4C 00 :Apple beacon
02 :type ( constant ,defined by ibeacon spec )
15 :length ( constant defined by ibeacon spec )
A4 95 BB 20 C5 B1 4B 44 B5 12 13 70 F0 2D 74 DE :device UUID
00 4A :major - temperature (in degrees fahrenheit)
03 F1 :minor - specific gravity (x1000)
22 signal power ?? maybe

Is there a sketch that allows me to get the manufacturer data by passing the address as a parameter ?

If the BLE_scan program (which you have not posted) can display the values you are interested in then I'm sure it can be adapted to do other stuff with those values.

What have you tried?

...R

Here is the BLE_scan sketch:

/*
   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
   Ported to Arduino ESP32 by Evandro Copercini
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

int scanTime = 5; //In seconds
BLEScan* pBLEScan;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
    }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Scanning...");

  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop() {
  // put your main code here, to run repeatedly:
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
  Serial.print("Devices found: ");
  Serial.println(foundDevices.getCount());
  Serial.println("Scan done!");
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  delay(2000);
}

Here is the BLEAdvertisedDevice.h

The interesting part looks like at line 34 std::string getManufacturerData();

/*
  * BLEAdvertisedDevice.h
  *
  *  Created on: Jul 3, 2017
  *      Author: kolban
  */
 
 #ifndef COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_
 #define COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_
 #include "sdkconfig.h"
 #if defined(CONFIG_BT_ENABLED)
 #include <esp_gattc_api.h>
 
 #include <map>
 
 #include "BLEAddress.h"
 #include "BLEScan.h"
 #include "BLEUUID.h"
 
 
 class BLEScan;
 class BLEAdvertisedDevice {
 public:
     BLEAdvertisedDevice();
 
     BLEAddress  getAddress();
     uint16_t    getApperance();
     std::string getManufacturerData();
     std::string getName();
     int         getRSSI();
     BLEScan*    getScan();
     BLEUUID     getServiceUUID();
     int8_t      getTXPower();
 
     bool        haveAppearance();
     bool        haveManufacturerData();
     bool        haveName();
     bool        haveRSSI();
     bool        haveServiceUUID();
     bool        haveTXPower();
 
     std::string toString();
 
 private:
     friend class BLEScan;
 
     void parseAdvertisement(uint8_t* payload);
     void setAddress(BLEAddress address);
     void setAdFlag(uint8_t adFlag);
     void setAdvertizementResult(uint8_t* payload);
     void setAppearance(uint16_t appearance);
     void setManufacturerData(std::string manufacturerData);
     void setName(std::string name);
     void setRSSI(int rssi);
     void setScan(BLEScan* pScan);
     void setServiceUUID(BLEUUID serviceUUID);
     void setTXPower(int8_t txPower);
 
     bool m_haveAppearance;
     bool m_haveManufacturerData;
     bool m_haveName;
     bool m_haveRSSI;
     bool m_haveServiceUUID;
     bool m_haveTXPower;
 
 
     BLEAddress  m_address = BLEAddress((uint8_t*)"\0\0\0\0\0\0");
     uint8_t     m_adFlag;
     uint16_t    m_appearance;
     int         m_deviceType;
     std::string m_manufacturerData;
     std::string m_name;
     BLEScan*    m_pScan;
     int         m_rssi;
     BLEUUID     m_serviceUUID;
     int8_t      m_txPower;
 };
 
 class BLEAdvertisedDeviceCallbacks {
 public:
     virtual ~BLEAdvertisedDeviceCallbacks() {}
     virtual void onResult(BLEAdvertisedDevice* pAdvertisedDevice) = 0;
 };
 
 #endif /* CONFIG_BT_ENABLED */
 #endif /* COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_ */

Biasedturkey:
The interesting part looks like at line 34 std::string getManufacturerData();

So what happened when you tried using that function ?

...R

I completed the following sketch.
The tilt hydrometer address is defined at :
String knownAddresses[] = { "f7:44:3e:01:7f:36"};

The Tilt address is found using an Android Beacon Scanner.
The Gravity and temperature are displayed on the arduio IDE terminal.

#include "BLEDevice.h"
int Lampara = 33;
int Contador = 0;
long Temperature;
long Gravity;
float TempDec;
float GravDec;
static BLEAddress *pServerAddress;
BLEScan* pBLEScan;
BLEClient*  pClient;
bool deviceFound = false;
bool Encendida = false;
bool BotonOff = false;
String knownAddresses[] = { "f7:44:3e:01:7f:36"};
unsigned long entry;
static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
  Serial.print("Notify callback for characteristic ");
  Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
  Serial.print(" of data length ");
  Serial.println(length);
}
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice Device){
      //Serial.print("BLE Advertised Device found: ");
      //Serial.println(Device.toString().c_str());
      pServerAddress = new BLEAddress(Device.getAddress()); 
      bool known = false;
      bool Master = false;
      String ManufData = Device.toString().c_str();
      String TempHex = ManufData.substring(95,99 ); 
      String GravHex = ManufData.substring( 99,103 );

      //long Temperature =  strtol( TempHex.c_str, NULL, 16 );
      
      for (int i = 0; i < (sizeof(knownAddresses) / sizeof(knownAddresses[0])); i++) {
        if (strcmp(pServerAddress->toString().c_str(), knownAddresses[i].c_str()) == 0) 
          known = true;
      }
      if (known) {
        Serial.print("Device found: ");
        Serial.println(Device.getRSSI());
        
        
        Serial.print("Temperature   ");
        Serial.print(TempHex);
        Serial.print ("    " );
        Temperature = strtol( TempHex.c_str() , NULL, 16 );
        TempDec = ( (Temperature - 32.0 ) * (5.0 / 9.0 ));
        Serial.println ( TempDec );
         //Serial.println( Temperature );
        //Serial.println(strtol(TempHex.c_str(), NULL, 16));

        Serial.print("Gravity   ");
        Serial.print(GravHex);
        Serial.print ("    " );
        Gravity = strtol ( GravHex.c_str() , NULL, 16 );
        GravDec = ( Gravity / 1000.0 );
        Serial.println( GravDec ,3 );
        //Serial.println( Gravity );
        //Serial.println(strtol(GravHex.c_str(), NULL, 16));

        
        
        if (Device.getRSSI() > -85) {
          deviceFound = true;
        }
        else {
          deviceFound = false;
        }
        Device.getScan()->stop();
        delay(100);
      }
    }
};
void setup() {
  Serial.begin(115200);
  pinMode(Lampara,OUTPUT);
  digitalWrite(Lampara,LOW);
  BLEDevice::init("");
  pClient  = BLEDevice::createClient();
  pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  Serial.println("Done");
}
void Bluetooth() {
  Serial.println();
  Serial.println("BLE Scan restarted.....");
  deviceFound = false;
  BLEScanResults scanResults = pBLEScan->start(5);
  if (deviceFound) {
    Serial.println("Encender Lamara");
   
    Encendida = true;
    digitalWrite(Lampara,HIGH);
    Contador = 0;
    delay(10000);
  }
  else{
    digitalWrite(Lampara,LOW);
    delay(1000);
  }
}
void loop() { 
  Bluetooth();
}
1 Like

Does Reply #4 mean that the problem is solved?

...R

Yes, problem solved, but I don't know how to show that it is solved.

Biasedturkey:
Yes, problem solved, but I don't know how to show that it is solved.

The usual thing is to edit your Original Post and add the word [SOLVED] to the title.

...R