esp32-snippets icon indicating copy to clipboard operation
esp32-snippets copied to clipboard

BLE Library - Please add Major/Minor

Open BladeRunner68 opened this issue 7 years ago • 32 comments

I'm looking at using your BLE libs in the ESP32 for scanning and getting major and minor values from a BLE hydrometer (Tilt)

According to the Apple Ibeacon spec: "The UUID, major and minor values provide the identifying information for the iBeacon. "

https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf

The makers of the Tilt hydrometer are using the Major and Minor fields to hold variable gravity and temperature values without having to connect directly to the BLE device (thus saving the device battery). This makes the values discoverable by a simple ble scan on a regular basis.

Any chance you can amend the libs to add getters for these values please?

BladeRunner68 avatar Dec 12 '17 22:12 BladeRunner68

The good news is that the capability you seek is already available.

When you are being a BLE Client and performing a scan, for each received advert, you are given an instance of the "BLEAdvertisedDevice". This is the description of the device that is doing the advertising.

Now let us turn our attention to a device that IS advertising ... review the following:

  • https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf
  • https://os.mbed.com/blog/entry/BLE-Beacons-URIBeacon-AltBeacons-iBeacon/

You will find that the "beacon" data is advertised in an ordinary BLE Advert and the data you are looking for is contained within the Manufacturer Data portion.

This means that when you get a BLEAdvertisedDevice you can perform code similar to the following:

struct {
  uint16_t manufacturerId;
  uint8_t subType;
  uint8_t subTypeLength;
  uint16_t uuid;
  uint16_t major;
  uint16_t minor;
  uint8_t power;
} beaconRecord;
...
struct beaconRecord *pBeaconRecord = (struct beaconRecord *)(myAdvertisedDevice->getManufacturerData().data());
printf("major: %d, minor: %d", pBeaconRecord ->major, pBeaconRecord ->minor);

Note that I coded this here in github so haven't tested it.

nkolban avatar Dec 13 '17 01:12 nkolban

See also #196

nkolban avatar Dec 15 '17 23:12 nkolban

A new class called BLEBeacon has been added ... see #196.

nkolban avatar Dec 16 '17 04:12 nkolban

I was looking at you news BLEAdvertising.h under snippets and wondering if should I copy those under ESP_32_Arduino BLE without pain or better wait for an upgrade and a beacon example working under Arduino.

qrpfun avatar Dec 17 '17 17:12 qrpfun

What keeps you to not copy it? If it wont works for some reason then you can delete it. Only thing is, if you need to replace files with the same name then make backup.

chegewara avatar Dec 17 '17 17:12 chegewara

You are absolutely right ..later I will do a it and will let you know if somethings brakes. But are not so clear right ways to use them .. let’s try

Inviato da iPhone

Il giorno 17 dic 2017, alle ore 18:30, chegewara [email protected] ha scritto:

What keeps you to not copy it? If it wont works for some reason then you can delete it. Only thing is, if you need to replace files with the same name then make backup.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

qrpfun avatar Dec 17 '17 18:12 qrpfun

OK done Copied BLEAdvertising.* and need to copy BLEUUID.* too for some dependencies. Changed BLE_server examples to BLE_server_iBeacon according to #196 suggestions Everything runs but no special data seen on iPhone (apps nRF Connect and LightBlue) Here's nRF Connect snapshot https://www.dropbox.com/s/5iyt5u1zvvcm7gr/Foto%2017-12-17%2C%2020%2054%2037.png?dl=0

Any tips ?

Here is the code:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setValue("Hello World says Neil");
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  
  Serial.println("Building up iBeacon advertising ..");
  BLEBeacon myBeacon;
  // Setting up according to https://os.mbed.com/blog/entry/BLE-Beacons-URIBeacon-AltBeacons-iBeacon/
  myBeacon.setManufacturerId(uint16_t (0x1AFF));
  myBeacon.setMajor(uint16_t (0x1234));
  myBeacon.setMinor(uint16_t (0x5678));
  myBeacon.setProximityUUID(uint16_t (0x004C));
  myBeacon.setSignalPower(0xC8);
  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(ESP_BLE_ADV_FLAG_LIMIT_DISC | ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT);
  // Build the iBeacon data structure and store it in std::string beaconData
  advertisementData.setManufacturerData(myBeacon.getData());
  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

qrpfun avatar Dec 17 '17 19:12 qrpfun

@qrpfun Is it still not working for you?

chegewara avatar Dec 31 '17 02:12 chegewara

@chegewara I did some other test but without any success, so then I give up taking care if some other updates should be useful to solve it. But not much time last weeks. Did you have any new idea about it ?

@qrpfun Is it still not working for you?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

qrpfun avatar Dec 31 '17 07:12 qrpfun

@qrpfun Im not sure if its still working, but at the publish time its been working https://github.com/chegewara/esp32-tests-library/tree/master/ibeacon_test

If you will find any issues running it just let us know

chegewara avatar Dec 31 '17 07:12 chegewara

@chegewara thanks for the new advice. I have tried again with your code, that's not different from mine, but no result at all. May be the problem is in the rest of the arduino libs, maybe in the iPhone bluetooth stack.

qrpfun avatar Dec 31 '17 15:12 qrpfun

@qrpfun Thats the problem, you are trying to find not genuine iBeacon with iPhone. Apple sucks (opinion) so much in many ways. If you will check esp-idf issues you can see that espressif devs advise to not use iBeacon with iPhone (i think so). But i will check it out one more time and write arduino ibeacon, but i dont have apple device to make real tests.

chegewara avatar Dec 31 '17 15:12 chegewara

@chegewara maybe that's the problem. I should check with an android device I do not have any one now. by now many thanks and have an happy new year !!

On Sun, Dec 31, 2017 at 4:31 PM, chegewara [email protected] wrote:

@qrpfun https://github.com/qrpfun Thats the problem, you are trying to find not genuine iBeacon with iPhone. Apple sucks (opinion) so much in many ways. If you will check esp-idf issues you can see that espressif devs advise to not use iBeacon with iPhone (i think so). But i will check it out one more time and write arduino ibeacon, but i dont have apple device to make real tests.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/271#issuecomment-354609890, or mute the thread https://github.com/notifications/unsubscribe-auth/AP1uezWqyrRbsKRor6LKBGtWd2ukOYJoks5tF6jdgaJpZM4Q_tlM .

-- Giampiero Raschetti

qrpfun avatar Dec 31 '17 17:12 qrpfun

Hi Guys - I'm a complete beginner at C++ so looking for some help if possible to get the major and minor values from the call to myAdvertisedDevice->getManufacturerData().data() as per Neil's example above.

Thanks for any help.

BladeRunner68 avatar Jan 03 '18 09:01 BladeRunner68

Howdy @BladeRunner68 .... I'm thinking your question should be posted to its own issue? This thread has been exclusively about an ESP32 BEING a BLE beacon. I think you are asking about an ESP32 BEING a client to external BLE beacons?

If so, can I ask you to create a whole new issue and we'll track it there?

nkolban avatar Jan 04 '18 00:01 nkolban

Hi @nkolban , I'm a bit confused as i created this particular issue back in December to ask about getting the major and minor values from a scan. I can create a separate question if you want but if you review the first couple of points in this issue then review, we can take it further based on your view?

Thanks

BladeRunner68 avatar Jan 04 '18 06:01 BladeRunner68

Howdy @BladeRunner68 ... its very likely I missed something ... and re-reading the whole thread from the start and will be back shortly. My goal is to delight .... lets see if I can make that goal :-)

Doh!!! I see now that this thread is indeed YOUR thread ... and it was piggybacked by others .... studying your question now.

nkolban avatar Jan 04 '18 23:01 nkolban

What we have now done is refactored some code and "hopefully" made things easier. A while back we created a class (BLEBeacon) that provided a way for an ESP32 to become an iBeacon however we neglected to see that the class could also be used to receive data from an iBeacon.

I will assume that you are running your ESP32 as a BLE Client and that you are performing scans. When a advert arrives AND you have good faith that the advert represents an iBeacon, you can now call:

BLEBeacon myBeacon;

myBeacon.setData(myAdvertisedDevice->getManufacturerData());

In English, what we are saying in the above is "Create me an instance of a class called BLEBeacon" and make the variable myBeacon represent that instance. Next we call the setData() method of the BLEBeacon which takes as input the manufacturer data received in an advert. Once done, we can now call the methods on the BLEBeacon instance to retrieve the content of the beacon data. These include:

  • getMajor()
  • getMinor()
  • getManufacturerId()
  • getProximityUUID()
  • getSignalPower()

Let's see how you get on with this. Make a first pass attempt at getting something working but don't struggle too much if it is confusing. Instead, post a link to a pastebin of your code and what issues/symptoms you are finding and we'll iterate forward together to get you going.

nkolban avatar Jan 05 '18 00:01 nkolban

Hey @nkolban thanks very much for the code inclusions - no doubt at all that these additions will help me (and others) - particularly the getters. I'll have a bash at some coding this weekend and revert back.

BladeRunner68 avatar Jan 05 '18 12:01 BladeRunner68

And please ... don't be shy. If we can be of ANY assistance, don't hesitate to ask. We are happy to help and meet you more than half way.

nkolban avatar Jan 05 '18 14:01 nkolban

@nkolban just for an update: I have imported changes in Arduino IDE by simply copying BLEAdvertising.* BLEBeacon.* and BLEUUID.h and it compiles without any problem.

Using this server code on iPhone, iBeacons data still fails https://pastebin.com/HYyGT5K2

here's raw data view in nRF Connect foto 06-01-18 15 24 34

qrpfun avatar Jan 06 '18 14:01 qrpfun

Howdy mr @qrpfun .... If I'm understanding correctly, your puzzle is about using the ESP32 as a BLE beacon which is broadcasting information. I am thinking that mr @BladeRunner68 puzzle is about using the ESP32 as a BLE advertizing receiver that is receiving incoming BLE adverts from external (real world) beacons.

To my thinking these are distinct puzzles. Since this current issue was created first by mr @BladeRunner68 what I'd like to suggest is that you go ahead and create a whole new issue containing your story and documentation. What we'll then do is give you good attention on your puzzle. I think that would be best for all as when we read an issue, it gets complicated when we start to intertwine multiple stories.

nkolban avatar Jan 06 '18 15:01 nkolban

Howdy mr @nkolban . There was some misunderstanding in the beginning while using iBeacon data structure but You are absolutely right, I'm sorry. I will follow your suggestion asap and create whole new issue. thanks for your kind support

qrpfun avatar Jan 06 '18 20:01 qrpfun

@BladeRunner68 have you had any success finding TILTs with the esp32? I'm actually trying to get it to do the same thing. I'd like to use the values in a temperature controller example

rawestmoreland avatar Jan 15 '18 03:01 rawestmoreland

@rawestmoreland not yet - @nkolban added some great features in the c++ lib but it appears these are not yet accessible by the Arduino/Platformio envs and as such i've put this on hold for a while as I don't have the time anymore to pick this up.

BladeRunner68 avatar Jan 15 '18 22:01 BladeRunner68

@nkolban I am trying to scan for iBeacons using esp32. I have used the method you suggested using BLEBeacon myBeacon; But when I do

getMajor()
getMinor()

I get something like this:

54245 23242

This value does not correspond to any of our iBeacons. I was wondering if the return values from this methods are in int or do they need any further manipulation there. Thanks in advance.

Atul141 avatar Feb 28 '18 11:02 Atul141

It should have return int16 value. I dont have any iBeacon so i cant test this code, but there is small chance that value needs to be changed from little to big endian before get returned to user. If you can post value that you expect and value you have received then i could have confirm that.

ie if im right and you get 54245 then real value advertised by iBeacon is 58835 or hex 0xe5d3

chegewara avatar Feb 28 '18 12:02 chegewara

@chegewara
Converting little endian to big endian worked well !! Thanks a lot for the solution.

Atul141 avatar Mar 01 '18 06:03 Atul141

I'm using esp32 as ibeacon scanner. I find this thread after two days, this helped me a lot. thanks every one. Now i have problem with UUID that i'm getting from "getProximityUUID()". the problem is, last two characters of uuid are missing. Annotation 2019-09-29 124922 image

can any help me with this. How can i get the whole uuid.

in start i was not getting correct uuid so i set the msbfirst to true then i got correct uuid(screen shot is attached below). but in every case last characters are missing
Annotation 2019-09-29 123329

my code is ` class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice Device) { //Serial.print("BLE Advertised Device found: "); Serial.println(Device.toString().c_str()); //Serial.println(ENDIAN_CHANGE_U16(myBeacon.getMajor())); BLEBeacon myBeacon; String UUID; pServerAddress = new BLEAddress(Device.getAddress()); Serial.println(pServerAddress->toString().c_str());

  if (Device.haveManufacturerData())
  {
    myBeacon.setData(Device.getManufacturerData());
    UUID = myBeacon.getProximityUUID().toString().c_str();
    //BLEUUID(m_beaconData.proximityUUID, 16, false)
    //Serial.println(BLEUUID(UUID.c_str(),16,false).toString().c_str());
    Serial.println(UUID);

    if (saveUUID)
    {
      appendFile(SD, "/UUIDs.txt", UUID.c_str());
      appendFile(SD, "/UUIDs.txt",",");
      readFile(SD, "/UUIDs.txt");
      saveUUID=false;
    }
  }
  Serial.println("______________________");
}

}; `

arslan437 avatar Sep 29 '19 07:09 arslan437

Hi, its hard to say what is wrong because i dont see problem with library. Here is beacon structure: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEBeacon.h#L18-L26

You can try to print beacon HEX values in next line where its bugged value. Beacon length is 25 bytes.

chegewara avatar Sep 29 '19 22:09 chegewara