Bluetooth Low Energy in Practice: Lessons from the Field

Simon

Simon Bradley

18 November 2025

18 Nov 2025

18/11/25

11 MIN READ

11 MIN READ

Apple App Clips
Apple App Clips
Apple App Clips

Bluetooth Low Energy (BLE) has become a go-to technology for everything from wearables to asset tracking, and, on paper, it seems ideal: low power, widely supported, and flexible enough to cover everything from simple broadcast beacons to full two-way communication.

But, once you're out of the lab and into the field (say, quite literally in a grain facility in Western Australia), things start to look different. You quickly run into quirks you didn't anticipate: unstable MAC addresses, mysteriously disappearing packets, and phones that behave differently for no apparent reason. And if you're trying to do it securely? That's a whole other can of worms.
In this post, I'll walk through some of the best practices and hard-earned lessons from deploying BLE in a real-world environment where signal strength isn't always reliable, latency matters, and security isn't optional.


Choosing the Right Protocol: iBeacon, Eddystone, or Secure Custom?

When most developers start working with BLE, they gravitate towards well-known formats like iBeacon or Eddystone. They're simple, documented, and supported by plenty of libraries and SDKs. And, for basic use cases (like proximity detection or signage triggers), they're often good enough.

But, when your application involves real assets, real environments, and real data, things get more serious. In our case, BLE packets were identifying industrial hardware and triggering automated events. That meant we had to think about security. With Eddystone, for example, anyone with a phone and a scanner app can spoof or sniff your beacon traffic. There's no authentication, no encryption, and no integrity check.

That's where vendor-specific protocols like Kontakt.io's Secure Profile come in. These offer encrypted, authenticated packets with support for dynamic identifiers and secure telemetry. You lose some openness and portability (and yes, you're tied to a specific ecosystem), but, in exchange, you gain real protection against spoofing and replay attacks.

Best practice? If your beacons are doing more than just broadcasting a room name, don't rely on iBeacon or Eddystone alone. Either wrap their contents in encrypted payloads yourself, or use a protocol designed with security in mind from the start.


Don't Assume the MAC Address Is Stable

One of the first things you learn when working with BLE is that every device has a MAC address. So, naturally, you assume you can use it to uniquely identify beacons, right? Unfortunately, that assumption doesn't hold up, especially if you're targeting iOS or working with devices that use randomised addresses for privacy.

Modern operating systems (and many BLE stacks) deliberately hide or rotate MAC addresses to prevent persistent tracking. iOS does not expose the MAC address of a detected peripheral at all. Instead, it provides a stable, app-specific UUID that is not derived from the MAC address. Android is more flexible but still varies behaviour across versions and manufacturers.
If you build your logic around MAC addresses, things will work great in the lab and break unpredictably in production.

The better approach is to use a stable, protocol-defined identifier. For example:

  • Eddystone-UID provides a 16-byte unique ID in the advertising payload

  • Kontakt's Secure Profile includes a securely signed identifier that can't be spoofed

Best practice? If you absolutely must track a beacon across sessions, use what's inside the packet, not what's outside it.


RSSI Lies (But Can Be Useful)

RSSI (the Received Signal Strength Indicator) is one of those numbers that feels scientific, but acts more like a mood ring. It's affected by walls, people, device orientation, humidity, and whether someone walked past with a metal clipboard. And it changes from moment to moment, even if nothing seems to be moving.

That said, RSSI isn't useless. It's just misunderstood. If you're trying to calculate a precise distance from a beacon using RSSI and Tx Power, you're going to be disappointed. The result might be accurate in a vacuum chamber, but out in the world? Expect noise and drift.

What does work is using RSSI for proximity zones:

  • Very strong signal: probably close

  • Very weak signal: probably far

  • Intermediate values: good enough to sort devices by relative proximity

In our app, we estimate distance by combining Kontakt Secure Profile packets (which include Tx Power) with the observed RSSI. Initially, the results were only consistent when the environment was stable, which, in a busy operational setting, is hard to guarantee. By averaging signal strength over time, we're now able to determine the nearest beacon with reasonable reliability.
Bluetooth 5.1 introduced support for Angle of Arrival and Angle of Departure, which should improve proximity estimation significantly. However, adoption of this feature has remained relatively low as of mid-2025.

Best practice? Treat RSSI as a hint, not a measurement. It's useful for detecting when a beacon is near, or when it's gone, but, if your use case depends on fine-grained distance estimation, you'll need more than just signal strength.


Use Coded PHY If Range Is King

In most BLE deployments, you're working within a few metres: a room, a hallway, maybe a warehouse. But, if you're trying to reach sensors out in the paddock, things get a little harder. That's where LE Coded PHY, introduced in Bluetooth 5, can make a real difference.

Coded PHY trades raw speed for range and reliability. Instead of transmitting each bit once, it encodes it into multiple symbols, spreading the information out so it can survive interference, fading, and distance. The result? You can get 2 to 4 times more range at the same power level, without needing to crank up the transmitter.

The downside is throughput. LE Coded operates at 500 kbps or even 125 kbps (compared to 1 or 2 Mbps on uncoded PHYs), so it's not ideal for bulk data. It also takes longer to send each packet, which can affect latency, if you're polling multiple devices.

In our experience, it's a great fit for long-range, low-volume use cases, like detecting the presence of equipment or sensors spread across a large outdoor area. Not all phones support it (especially older ones), but, for dedicated scanning hardware or tightly controlled environments, it's worth considering.

Best practice? If your packets are small and your distances are large, don't dismiss Coded PHY. It's not just for "fancy" IoT. Sometimes, it's the only thing that works when you need to punch through air, walls, or corrugated iron.


Test With Real Devices and Real Movement

It's easy to build a BLE feature that works perfectly in your office, on your phone, with your hand hovering precisely 20 centimetres above the beacon. The real world, unfortunately, is less cooperative.

Once you take your app into the field (or the factory, or the paddock), a whole range of new factors come into play: moving vehicles, signal reflections, cheap Android phones with dodgy antennas, and users who wave their phones around like they're trying to swat a fly. The difference in behaviour between devices can be dramatic, especially when you're relying on things like scan intervals, background scanning support, or how quickly a beacon appears in a filtered list.

In one test environment, we found that two different Android phones placed side by side picked up the same beacon at noticeably different signal strengths and timings, and one of them didn't detect the beacon at all until it was nearly on top of it. That's not something you'll spot unless you're testing in messy, noisy, real-world conditions.

Best practice? Don't just test your BLE implementation with your dev phone and a clean desk. Test it in the environment where it will actually be used, and with the kind of hardware your users have, not just the high-end devices your team happens to carry.


Favour Push, Not Poll

One of the easiest mistakes to make when designing a BLE system is thinking like a traditional client-server app: "I'll just connect to the device and ask it for data every few seconds." That works in theory, until you scale up, hit power limits, or try it across multiple devices at once.

BLE is built around the idea of low power, event-driven communication. Maintaining a connection and polling for data burns far more energy (on both the beacon and the phone) than simply listening for broadcasts. It also adds complexity: reconnecting, handling timeouts, and juggling multiple concurrent connections.

In our system, we rely on short, frequent advertising packets that contain just enough information to identify the beacon and trigger business logic (like logging events or updating status in our backend). This avoids unnecessary connections, lets multiple devices observe the same beacon simultaneously, and keeps power usage low.

At present, we don't use the app to update firmware or push configuration changes to the beacons, that still requires an administrator to visit the site and do it manually. But, in the future, we plan to allow the app to connect and perform updates automatically based on the latest configuration in Kio Cloud (Kontakt.io's cloud-based beacon management platform). That's a good example of when a connection does make sense: infrequent, intentional, and doing something that can't be done via broadcast alone.

Best practice? Broadcast what you can, connect only when you must. If your beacons can get the job done just by being seen, let them.


Security: Encrypt Early, Authenticate Always

It's easy to assume that Bluetooth Low Energy is secure by default, after all, it's a wireless protocol, and it supports pairing, right? But, when it comes to advertising, things are very different. BLE advertisement packets are broadcast in plaintext to anyone who's listening. That means, if your beacons are sending out anything sensitive (like identifiers, telemetry, or state), it's all visible to anyone nearby with a phone or a laptop.

Neither iBeacon nor Eddystone includes any kind of built-in authentication or encryption. Anyone can sniff their packets, copy them, and spoof those beacons elsewhere. That might be fine for triggering a marketing message in a shopping mall, but, in any system where beacon identity matters, it's a real risk.

We chose to use Kontakt's Secure Profile for this reason: the packets are encrypted and signed, meaning we can trust both the origin and integrity of the data. That alone prevents a whole class of spoofing and replay attacks, without requiring us to maintain connections or perform complex key exchanges on the fly.

Of course, not everything needs to be encrypted, but it's good practice to assume that anything in an advertising packet is public, and to treat it accordingly. If your application logic depends on trusting the data in a packet, sign it, encrypt it, or don't use it.

Best practice? Don't assume BLE security is "on" unless you've explicitly built it in. Use secure protocols where available, avoid broadcasting secrets, and make authentication part of your design, not an afterthought.


Tooling: Get Friendly with Sniffers and Logs

When BLE works, it feels like magic. When it doesn't, it feels like you're debugging with your eyes closed. Packet timing, signal strength, and even which packets are received can all vary between devices, and, without the right tools, you're left guessing.

One of the most helpful things we did was set up proper logging and sniffing early in development. For on-device testing, apps like nRF Connect (Android and iOS) are invaluable, they let you scan, connect, and inspect services and characteristics interactively. For raw advertising data, they give you a live view of what's actually being broadcast and picked up.

When that's not enough, a proper BLE sniffer can help. Nordic and TI both make USB-based sniffers that work with Wireshark, allowing you to see packets over the air, timestamped and decoded. That's especially useful when you're trying to debug missed packets, protocol mismatches, or unexpected retries, or when you're just not sure whether the beacon is broadcasting at all.

And finally: logs. Whether it's your own app or a vendor SDK, make sure you have access to detailed logs of what's being seen, parsed, and ignored. BLE is sensitive to small things, packet structure, timing, background scan settings, and logs will save you hours when something silently fails.

Best practice? Give yourself visibility. The BLE layer is low-level and timing-sensitive, and a good set of tools makes the difference between flying blind and diagnosing real issues quickly.

Final Thoughts: What the Specs Don't Teach You

BLE is one of those technologies that seems simple until you try to do something non-trivial with it. The core ideas (low power, short packets, event-driven communication) are elegant. But, once you step outside a controlled environment, you quickly learn that real-world BLE development is less about specs and more about trade-offs.

Should you use iBeacon, Eddystone, or a secure custom format? Should you broadcast or connect? Should you calculate distance or just settle for "near enough"? The answers depend not just on the protocol, but on the environment, the hardware, the phones, and (often) what's practical to maintain.

If there's one theme that came up again and again in our deployment, it's this: BLE rewards a realistic mindset. Focus on reliability, build in security, and test like your environment matters, because it does.

TL;DR: Best Practices at a Glance

  • 📡 Broadcast what you can, connect only when you must

  • 🔒 Use secure profiles or encrypt the data yourself

  • 📶 Treat RSSI as a hint, not a ruler

  • 🔄 Avoid relying on MAC addresses, use stable IDs instead

  • 🧪 Test with real devices, in real places

  • 🔧 Invest in tooling, sniffers and logs pay for themselves

  • 📏 Consider Coded PHY when range is more important than speed

BLE is subtle. But, with the right practices, it can be solid, too.