Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save donnywals/39d0c8ffd22a2f3e631f to your computer and use it in GitHub Desktop.
Save donnywals/39d0c8ffd22a2f3e631f to your computer and use it in GitHub Desktop.

Dan Lederman - Conquering CoreBluetooth, a survival guide

  • BLE (Bluetooth Low Energy) is the only way to communicate with devices without pairing at all. You can read and write some data without even taking your phone out of your pocket. During the talk we will investigate a running app that allows people to make some data available across runners. This includes things like username, heart rate, distance, elevation etc. Also, this will be platform agnostic.
  • You use a Peripheral, this will advertise some services. Heart rate and run. The information that these Peripherals publish are called characteristics. Setting up a Peripheral requires a delegate and some options. This allows the PeripheralManager to run in the background. When the manager calls didUpdateState we know if the user has bluetooth enabled and we can ask them to turn it on. Then we call addService, you pass that a new service and you add characteristics. (CBMutableService and CBCharacteristics). Bluetooth is unstable and if you don’t treat it right it can stop calling callbacks. We’re going to be gentle and prefer read-only. Once the services are added you can call startAdvertising. You pass that the UUIDs for your services.
  • Once you’re set up your Peripheral will call didReceiveReadRequest and you can figure out what was requested. When responding you have to make sure to implement all errors, if version 1.0 is asked for data it doesn’t support while version 2.0 does, your app can crash and look bad. The request you receive has an offset property. Because BLE can only support small data packages, the offset will tell you what part of your data you should be sending.
  • When your app gets killed in the background, iOS takes over your bluetooth service and when asked for data willRestoreState is called. If you’re read only you can just implement an empty method.
  • To read data from devices you use a CBCentralManager. The key you give it should be different that the Peripheral key so they don’t clash. Once your Central is created didUpdateState will be called. BLE advertising packets can only advertise a 37byte payload which is very tiny. Central connects to every Apple device it can find automatically. If you want to connect to others you have to scan for them yourself and connect to their peripherals.
  • Once you’ve connected to a peripheral you can set yourself as a delegate and start listening. After that you discover services, once that worked out you can disconnect if you don’t care about the services. After that you do the same for characteristics. In the end ‘didUpdateValieForCharacteristic` is called and after reading that you could disconnect from the peripheral. Doing this allows you to reconnect when done and then read again on the new cycle. If you don’t do this bluetooth might stop working and you’ve lost your connection. To support this you can kill your own central and restart it again. This should reboot the connection.
  • If you have an iOS8 and iOS9 device communicating together you get pairing dialogs that randomly appear and disappear. It’s all very strange.
  • Dan is going to release a cross-platform, open source library that allows for cross-platform communication between devices over bluetooth and it should take care of many bluetooth quirks.
  • Question: How did you feel while doing this? Why did you do this and did you feelings about CoreBluetooth change at all?
    • Answer: Because Dan works with payments and people sometimes want to split the bill, it would be nice if their phone numbers appear right away for example. Square has been trying to implement this for years, I though CoreBluetooth would never be able to do this. When iOS8 came out we were able to finally get this to work but CoreBluetooth would sometime still stop working and it all was a mess again. Right now I feel like, after iOS9 started dropping pairing dialogs, I was very mad. It’s just annoying.
  • Question: If you have a connection in the background will you find other devices and services as well?
    • You can find anything you want as long as your specific about what you’re looking for.
  • Question: You mentioned the offset while sending your data, what should you do if the data you’re sending can change?
    • You should cache the data so it’s immutable. You can throw it away when you’re done or reuse it if needed.
  • Question: You mention turning it off and on again, does your app keep running then? Is your app alive all the time?
    • No, iOS will take down your app after ±30 seconds but cycling the central will take about half a second. After apple shut down your app you central and peripheral will keep working, iOS takes care of this for you.
  • Question: Is there a limit to the number of devices you can find or talk to?
    • You can imagine that at square there’s a lot of people running our app. You can see like 20 devices at the same time but the less you can do, the better. And if it feels, turn it off and on again.
  • Question: Is the offset on the request a byte range?
    • Yes, you can use subDataWithRange to respond.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment