Iris Classon
Iris Classon - In Love with Code

Why Your BLE Manufacturer Data Disappears on macOS (.NET + CoreBluetooth)

If you’ve ended up here, I am sorry. I also hope you have not spent as much time as I did trying to figure out why the manufacturer data is always empty on the receiving end.

I have been working on a .NET MAUI BLE device emulator and realized, after an embarrassing amount of debugging, that Apple does not let us include more than a local name and service UUIDs when advertising with Core Bluetooth.

The supported keys are:

  • CBAdvertisementDataLocalNameKey
  • CBAdvertisementDataServiceUUIDsKey

Which is unfortunate, because I needed manufacturer data for my emulator devices. More precisely, I needed a way to send more data without connecting.

Apple’s approach is simple. Advertise just enough to connect, then exchange real data after connection. I would have saved myself a lot of time if I had internalized that earlier.

https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/startadvertising(_:)

My assumption was straightforward. If I can read manufacturer data when scanning, I should be able to send manufacturer data when advertising.

Nope. That symmetry does not exist here.

So, workarounds it is.

Option 1: Use GATT for the real data

Advertise just enough to be discovered, then use GATT for the actual data.

That means advertising a single service UUID, optionally adding a short local name, and then reading a characteristic after connecting. That characteristic can contain whatever you need, like serial number, firmware version, device role, owner tag, or location.

Option 2: Encode identity in the service UUID

Another option is to encode identity into the service UUID itself.

For example, you can use a fixed base UUID and let the last bytes represent device type, instance, or region. It is not pretty, but it is reliable on Apple platforms.

Option 3: Use the local name

You can also use the local name to carry a bit of extra information.

Something like DEbtn1, where DE stands for Device Emulator and btn1 identifies the device. You do not have many bytes to work with, but it is often enough to distinguish your devices in a crowded BLE environment.

If you have a smarter approach, I would love to hear it. For now, I am combining all three strategies in my emulator.

There will likely be more posts like this as I continue exploring CoreBluetooth and working with Bluetooth in .NET and .NET MAUI.

Comments

Leave a comment below, or by email.

Last modified on 2026-02-05

comments powered by Disqus