Skip to content

Add iBeacon example #971

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

Merged
merged 3 commits into from
Jun 3, 2025
Merged

Add iBeacon example #971

merged 3 commits into from
Jun 3, 2025

Conversation

lazd
Copy link
Contributor

@lazd lazd commented May 27, 2025

This example advertises an iBeacon that is recognized by Apple's CLLocationManager. I've tested this approach with a Swift app I'm building and it works great.

Based loosely on a previous Bluedroid implementation here, modified for NimBLE.

This is the example closes #911

cc @jdbravo

// Create advertisement data
NimBLEAdvertisementData beaconAdvertisementData;
beaconAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED
beaconAdvertisementData.setManufacturerData(reinterpret_cast<const uint8_t*>(&beaconData), sizeof(NimBLEBeacon::BeaconData));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious if there's a better way to do this, I noticed I can't directly pass beacon.getData() as it doesn't match any of setManufacturerData's signatures.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I see here is that this isn't needed. Instead what should be done is the beacon class should be fixed to include the flags since that is all that is happening here. They do not change in this repo as BT classic is not supported. Instead lets add this as a fixed data to the beacon data in the beacon class.

Copy link
Contributor Author

@lazd lazd May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds right to me, so what would the API end up looking like? Something like this would be nice:

advertising->setAdvertisementData(beacon.getAdvertisingData());

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay getting back to you. We can change this line to simply beaconAdvertisementData.setManufacturerData(beacon.getData());

In order to make that work you will need to add an operator to the beacondata class so it looks like :

    struct BeaconData {
        uint16_t manufacturerId{0x4c00};
        uint8_t  subType{0x02};
        uint8_t  subTypeLength{0x15};
        uint8_t  proximityUUID[16]{};
        uint16_t major{};
        uint16_t minor{};
        int8_t   signalPower{};
        operator std::vector<uint8_t> () const {
            return std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(this),
                                        reinterpret_cast<const uint8_t*>(this) + sizeof(BeaconData));
        }
    } __attribute__((packed));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented! Now all that is left would be to remove the need for this

beaconAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED

How should we go about doing that? Can we simply omit the call, or do we need to call setFlags() somewhere, like in the NimBLEAdvertisementData constructor?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave this for now, it would overly complicate things to accommodate.

Copy link
Owner

@h2zero h2zero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good, a couple of comments to work on.

// Create advertisement data
NimBLEAdvertisementData beaconAdvertisementData;
beaconAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED
beaconAdvertisementData.setManufacturerData(reinterpret_cast<const uint8_t*>(&beaconData), sizeof(NimBLEBeacon::BeaconData));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I see here is that this isn't needed. Instead what should be done is the beacon class should be fixed to include the flags since that is all that is happening here. They do not change in this repo as BT classic is not supported. Instead lets add this as a fixed data to the beacon data in the beacon class.

// Create advertisement data
NimBLEAdvertisementData beaconAdvertisementData;
beaconAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED
beaconAdvertisementData.setManufacturerData(reinterpret_cast<const uint8_t*>(&beaconData), sizeof(NimBLEBeacon::BeaconData));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave this for now, it would overly complicate things to accommodate.

@h2zero h2zero merged commit 84b79fd into h2zero:master Jun 3, 2025
41 checks passed
@h2zero
Copy link
Owner

h2zero commented Jun 3, 2025

Thanks!

@lazd
Copy link
Contributor Author

lazd commented Jun 3, 2025

Thanks for the guidance on landing this pR, glad I could contribute something back!

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

Successfully merging this pull request may close these issues.

iBeacon example version > 1.5
2 participants