Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLE Library - Please add Major/Minor #271

Open
BladeRunner68 opened this issue Dec 12, 2017 · 32 comments
Open

BLE Library - Please add Major/Minor #271

BladeRunner68 opened this issue Dec 12, 2017 · 32 comments
Assignees

Comments

@BladeRunner68
Copy link

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?

@nkolban
Copy link
Owner

nkolban commented Dec 13, 2017

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:

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
Copy link
Owner

nkolban commented Dec 15, 2017

See also #196

@nkolban
Copy link
Owner

nkolban commented Dec 16, 2017

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

@qrpfun
Copy link

qrpfun commented Dec 17, 2017

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.

@chegewara
Copy link
Collaborator

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.

@qrpfun
Copy link

qrpfun commented Dec 17, 2017 via email

@qrpfun
Copy link

qrpfun commented Dec 17, 2017

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);
}

@chegewara
Copy link
Collaborator

@qrpfun Is it still not working for you?

@qrpfun
Copy link

qrpfun commented Dec 31, 2017 via email

@chegewara
Copy link
Collaborator

@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

@qrpfun
Copy link

qrpfun commented Dec 31, 2017

@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.

@chegewara
Copy link
Collaborator

@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.

@qrpfun
Copy link

qrpfun commented Dec 31, 2017 via email

@BladeRunner68
Copy link
Author

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.

@nkolban
Copy link
Owner

nkolban commented Jan 4, 2018

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?

@BladeRunner68
Copy link
Author

BladeRunner68 commented Jan 4, 2018

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

@nkolban
Copy link
Owner

nkolban commented Jan 4, 2018

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 added a commit that referenced this issue Jan 5, 2018
@nkolban
Copy link
Owner

nkolban commented Jan 5, 2018

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.

@BladeRunner68
Copy link
Author

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.

@nkolban
Copy link
Owner

nkolban commented Jan 5, 2018

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.

@qrpfun
Copy link

qrpfun commented Jan 6, 2018

@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

@nkolban
Copy link
Owner

nkolban commented Jan 6, 2018

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.

@qrpfun
Copy link

qrpfun commented Jan 6, 2018

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

@rawestmoreland
Copy link

@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

@BladeRunner68
Copy link
Author

@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.

@Atul141
Copy link

Atul141 commented Feb 28, 2018

@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.

@chegewara
Copy link
Collaborator

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

@Atul141
Copy link

Atul141 commented Mar 1, 2018

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

@arslan437
Copy link

arslan437 commented Sep 29, 2019

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("______________________");
}

};
`

@chegewara
Copy link
Collaborator

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.

@arslan437
Copy link

OK i will try. But right now i did't have any Beacon device. I was using my brother's phone to simulate as Beacon(mine does not support beacon advertisement). But now he is gone for may be weak or two. I will test and post results soon.

Thank you for response.

@retsel89
Copy link

retsel89 commented May 5, 2021

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?

that is the ibeacon structure of payload data:
0 0x02 Data length – 2 bytes constant preamble
1 0x01 Data type – flags constant preamble
2 0x06 LE and BR/EDR flag constant preamble
3 0x1a Data length – 26 bytes constant preamble
4 0xff Data type - manufacturer specific data constant preamble
5 0x4c Manufacturer data constant preamble
6 0x00 Manufacturer data constant preamble
7 0x02 Manufacturer data constant preamble
8 0x15 Manufacturer data constant preamble
9 0xf7 Proximity UUID 1st byte set user UUID
10 0x82 Proximity UUID 2nd byte set user UUID
11 0x6d Proximity UUID 3rd byte set user UUID
12 0xa6 Proximity UUID 4th byte set user UUID
13 0x4f Proximity UUID 5th byte set user UUID
14 0xa2 Proximity UUID 6th byte set user UUID
15 0x4e Proximity UUID 7th byte set user UUID
16 0x98 Proximity UUID 8th byte set user UUID
17 0x80 Proximity UUID 9th byte set user UUID
18 0x24 Proximity UUID 10th byte set user UUID
19 0xbc Proximity UUID 11th byte set user UUID
20 0x5b Proximity UUID 12th byte set user UUID
21 0x71 Proximity UUID 13th byte set user UUID
22 0xe0 Proximity UUID 14th byte set user UUID
23 0x89 Proximity UUID 15th byte set user UUID
24 0x3e Proximity UUID 16th byte set user UUID
25 xx* Major 1st byte set major value
26 xx* Major 2nd byte set major value
27 xx* Minor 1st byte set minor value
28 xx* Minor 2nd byte set minor value
29 0xb3 Signal power (calibrated RSSI@1m) signal power value

you can get major and minor from bytes 25 to 28
hope that help, just code "advertisedDevice.getPayload()" and make a code for parse that structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants