Core Bluetooth

RSS for tag

Communicate with Bluetooth 4.0 low energy devices using Core Bluetooth.

Posts under Core Bluetooth tag

181 Posts

Post

Replies

Boosts

Views

Activity

BLE indications not always delivered to didUpdateValueFor
Im working on ios application that works with BLE device. The device uses BLE indications to provide data to the app. The goal is to achieve 100% data retrieval. According to the hardware team device behaves like this: CCCD Persistence: Device maintains Client Characteristic Configuration Descriptor (CCCD) with indication-enabled state across reconnections Resume Point: Device resends indications starting from the last unacknowledged indication before disconnection No Custom Logic: Follows standard BLE specification for indication reliability So it is expected that the device restores the indication streams from the last acknowledged one. My connection routine is: Discover services func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { connectedPeripherals[peripheral.identifier] = peripheral peripheral.delegate = self updatePeripheralState(peripheral.identifier, to: .connected) print("Starting service discovery...") peripheral.discoverServices(nil) } Discover characteristics: func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let error = error { print("Characteristic discovery failed for service \(service.uuid): \(error.localizedDescription)") return } guard let characteristics = service.characteristics else { return } for characteristic in characteristics { if service.uuid == targetServiceUUID && characteristic.uuid == targetCharacteristicUUID { print("Found target characteristic! Enabling indications...") peripheral.setNotifyValue(true, for: characteristic) print(characteristic.properties.description) } } } Then the data retrieval: func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { print("Error reading characteristic value: \(error.localizedDescription)") return } if characteristic.service?.uuid == targetServiceUUID && characteristic.uuid == targetCharacteristicUUID { if let data = characteristic.value { let formatter = DateFormatter() formatter.timeStyle = .medium formatter.dateStyle = .none // data filtering since device is sending some other events sometims if data.count >= 15 { let event = decodeBytes(bytes: data) let now = Date() let timestamp = timestampFormatter.string(from: now) print("[\(timestamp)] Auto Increment: \(event.autoIncrement) Type: \(event.type)") } } else { print("Received indication with no data") } } } Using PacketLogger from xcode toolbox i have confirmed that: The device starts sending indications right after didConnect finishes The phone is sending ACKS for those indications Indications are not reaching didUpdateValueFor until peripheral.setNotifyValue(true, for: characteristic) properly executes This mekes me drop some data data on each reconnect. I already know I can do better in terms of service and characteristics discovery: I should discover only that one which is giving me the indications. But my intuition is: discover only the service and characteristic i care about will minimize the impact, but not guarantee 100% data retrieval Is this expected and confirmed CoreBluetooth behavior?
2
0
84
Aug ’25
BLE Device Not Appearing in Scan List on iOS After Name Change
I'm encountering an issue related to BLE device discovery on iOS. I have a BLE peripheral device that I initially connected to using an iOS device. After this connection, the BLE device's advertised name was programmatically changed by the peripheral. Now, when I try to scan for this device using other iOS devices, it does not appear in the scan results in most apps — including nRF Connect and our own custom BLE app that uses CoreBluetooth. A few observations: The device is definitely powered on and advertising (confirmed via Android). The name change is reflected correctly on Android and on the iOS device that originally connected to it. Other iOS devices no longer see the device in their scan list.
1
0
319
Jul ’25
Best Practices for Unit Testing CoreBluetooth Applications - Seeking Official Guidance
Hello Apple Developer Community and Apple Engineers, I'm working on a CoreBluetooth-based iOS application and struggling to find clear, official guidance on best practices for unit testing CoreBluetooth functionality. I'd appreciate any insights from the community and especially from Apple engineers on the recommended approaches. Background & Challenges: Our team has encountered several challenges when trying to implement comprehensive testing for our CoreBluetooth code: Subclassing Restrictions: Apple's documentation explicitly states "Don't subclass any of the classes of the Core Bluetooth framework. Overriding these classes isn't supported and results in undefined behavior." This makes traditional mocking approaches (creating mock subclasses of CBCentralManager, CBPeripheral, etc.) problematic for unit testing. Integration vs Unit Testing Dilemma: We currently use integration tests with third-party libraries like Nordic Semiconductor's CoreBluetoothMock, which work well for end-to-end testing but aren't true unit tests. They test the interaction between our code and the (mocked) CoreBluetooth stack rather than testing individual methods in isolation. Delegate Method Testing: Our code implements CBCentralManagerDelegate and CBPeripheralDelegate protocols. Testing these delegate methods in isolation is challenging because: The methods receive CBCentralManager/CBPeripheral parameters that we can't mock via subclassing Using third-party mocking frameworks makes them integration tests, not unit tests Testing the business logic within these methods requires the actual CoreBluetooth objects Simulator Limitations: The only official Apple documentation we found about CoreBluetooth testing is Technical Note TN2295, which is marked as "retired" and from 2012. It describes a complex simulator setup requiring physical USB adapters, suggesting simulator-only testing isn't fully supported. Specific Questions: What are Apple's current official recommendations for testing CoreBluetooth applications? Should we focus on device testing, integration testing with mocking libraries, or are there other approaches we should consider? For unit testing: How can we test individual delegate methods and business logic without violating the "no subclassing" restriction? Are there patterns or architectures that make CoreBluetooth code more unit-testable? Testing strategy: Should CoreBluetooth applications primarily rely on integration tests rather than traditional unit tests? Is this an acceptable trade-off given the hardware-dependent nature of Bluetooth? Simulator support: Is there current, supported functionality for testing CoreBluetooth applications in the simulator, or should all testing be done on physical devices? Current Approach: We're currently using: Integration tests with CoreBluetoothMock for comprehensive workflow testing Limited unit tests for business logic that we can extract from delegate methods Physical device testing for final validation This works but feels incomplete compared to the unit testing coverage we achieve in other parts of our application. Request: Any guidance from Apple engineers on the intended/recommended approach for testing CoreBluetooth applications would be incredibly valuable. Even confirmation that "integration testing with physical devices is the primary recommended approach" would help clarify our testing strategy. Thank you for any insights you can share! Environment: iOS 17+ Xcode 15+ Swift 5.9+
0
0
133
Jul ’25
BLE Connection Failure with iPad A16 and Silicon Labs Gecko SDK 3.x Devices
We're seeing a consistent issue where iPads with the A16 chip fail to connect to our BLE device, which uses a Silicon Labs chip running Gecko SDK 3.x. All other Apple devices — including older iPads and iPhones — connect without any problems. According to Silicon Labs, the issue stems from the iPad A16 sending an LL_CHANNEL_REPORTING_IND message (opcode 0x28) during connection establishment: Per Silicon Labs: "Currently the iPad 16 will send a message for LL_CHANNEL_REPORTING_IND (opcode 0x28). This is a feature that is not supported in Gecko SDK 3.x. Shortly after, the BLE module responds with an 'Unknown Response' (opcode 0x07), indicating that it does not support opcode 0x28 After this exchange the iPad stops sending meaningful transactions to the BLE module and eventually closes the connection. The BLE Module is responding to this unknown request as specified in the BT Core Spec Volume 6 Part B." Unfortunately, the firmware on these BLE modules cannot be updated remotely, and we've already shipped several thousand units to customers. Given how widely Silicon Labs' BLE modules are deployed, we suspect this issue could be affecting many other developers and products as well. We’re hoping Apple might offer a workaround or allow us access — even internally or unofficially — to suppress or bypass this feature in CoreBluetooth for this specific scenario. For example, is there a way to disable LL_CHANNEL_REPORTING_IND or instruct the stack to ignore the unknown response from the peripheral? We’re open to any workaround via CoreBluetooth (even private APIs or entitlements, if necessary) that would allow us to preserve compatibility without a mass recall. If there's an Apple engineer monitoring this, we'd be extremely grateful for guidance or escalation. Thank you!
2
2
172
Jul ’25
Support for cycling power & cadence sensors in HKWorkoutSession on iOS?
Hi everyone, while testing HKWorkoutSession with HKLiveWorkoutBuilder on iOS 26 Beta (cycling workout), I noticed the following behavior: – Starting a cycling HKWorkoutSession automatically connects to my Bluetooth heart rate monitor and records HR into HealthKit ✅ – However, my Bluetooth cycling power meter and cadence sensor (standard BLE Cycling Power & CSC services) are not connected automatically, and no data is recorded into HealthKit ❌ On Apple Watch, when starting a cycling workout, these sensors do connect automatically and their data is written to HealthKit — which is exactly what I would expect on iOS as well. Question: Is this by design, or is support for power and cadence sensors planned for iOS in the same way as on watchOS? Or do we, as developers, need to implement the BLE Cycling Power and CSC profiles ourselves (via CoreBluetooth) if we want these metrics? Environment: – iOS 26 Beta – HKWorkoutSession & HKLiveWorkoutBuilder (cycling) – Bluetooth HRM connects automatically – BLE power & cadence sensors do not This feature would make it much easier to develop cycling apps with full HealthKit integration, and also create a more consistent user experience compared to watchOS. Thanks for any insights!
2
1
102
Jul ’25
WebSocket connection in background triggered by BLE accessory
Hello everyone, We are building an iOS app using React Native that connects to a custom Bluetooth Low Energy (BLE) accessory. The accessory continuously sends small chunks of audio data to the app through BLE (basically every time the user speaks), which are then streamed in real time to our server via WebSocket for transcription and processing. We need to know if the following behavior is allowed by iOS runtime and App Store review policies: Can the app open a WebSocket connection in the background (not permanently, just briefly, several times a day) triggered by BLE activity from a registered accessory? Is there a limit to this? Clarifications: The app is not expected to remain permanently awake. Only during accessory-triggered events. WebSocket is required due to the real-time nature of streaming STT and delivering quick responses (via notifications). If allowed, are there any specific Info.plist declarations or entitlements we must include? Thanks in advance! Fran
5
0
202
Jul ’25
What kind of feedback is available through tvOS Bluetooth HID?
first post here and this is kinda a long shot. I’m working on a custom keypad project for a young man with some mobility issues that unfortunately prevents gestrue and voice control as UI options. id like to see if I can pull track metadata via a Bluetooth connection into a custom keyboard with a small screen. I know hid doesn’t support this but I was hoping maybe the API for iOS’s blueprint remote app could be leveraged. I haven’t don’t much with Apple previousl. Usually Roku and Crestron implantations but I’m hoping to see if I can accomplish something with Apple, without needing to implement any IP connection.
0
0
52
Jul ’25
CBPeripheral delegate callback of `peripheralIsReady(toSendWriteWithoutResponse:)` doesn't happen when app in background
My team has an app that uses BTLE heavily, and has been doing so successfully, including no issues continuing to receive data in the background and updating things in the app (for recording workouts). We have a BTLE write queue that only tries to write when the CBPeripheral.canSendWriteWithoutResponse property is true, or when we get the notification from the system in peripheralIsReady(toSendWriteWithoutResponse:). This is used as a means to rate limit data transfer, as we transfer files, as well as require that packets always arrive in the correct order due to blob encoding. However, we had a new requirement come in to periodically write data out to a connected peripheral. I noticed that as soon as the app was in the background, despite other delegate callbacks coming in, like didRecieveUpdatedValue:, neither the property canSendWriteWithoutResponse nor the delegate callback were called any longer. This meant our write queue didn't think it had permission to write, and packets would just stack up. The failure to deliver these updates didn't occur immediately after backgrounding, but did within 2-5s of backgrounding. If, when in the background, I ignore the changing of that property, and instead just write the data to the peripheral, it works! Can anyone explain why, despite other CBPeripheral callbacks happening when in the background, this one does not?
2
0
429
Jul ’25
Example for AccessorySetupKit bluetoothTransportBriding
Hi there! I'm developing a dual-mode bluetooth accessory and would like to pair it through AccessorySetupKit. I'm using an ESP32 with Bluekitchen btstack. This supports CTKD, which seems to be a requirement for the Bluetooth transport bridging according the WWDC19 session 901. I've been in contact with the btstack developer and verified that I can get the device to generate an LTK for the classic transport when reading an encrypted attribute. I'm not able to get this to work with the bluetoothTransportBriding option with AccessorySetupKit though. What I've found so far is that if I omit the .bluetoothTransportBriding option during pairing I will get a pairing request when I read an encrypted attribute after connecting with the CBConnectPeripheralOptionEnableTransportBridgingKey option. If I accept this request it seems like the system automatically brings up the A2DP profile. However if I include .bluetoothTransportBriding and/or .bluetoothPairingLE this option does not pop up, but the system does not bring up the A2DP profile. In this case things seem to end up in a weird situation where the device doesn't show up for pairing in Bluetooth Settings either, making it impossible to manually connect for A2DP. Based on the AccessorySetupKit example from WWDC24 I've created a dice accessory firmware for ESP32 using btstack. The code for this is available here: https://github.com/ljodal/esp32-btstack-ctkd-test I've also tweaked the AccessorySetupKit example app for iOS to add the ASAccessory.SupportOptions. The code for that is available here: https://github.com/ljodal/accessorysetupkit-ctkd-test Is there any documentation available anywhere on what is expected of the device for Bluetooth Transport Bridging to work with AccessorySetupKit?
0
0
173
Jul ’25
CoreBluetooth and BLE AdvertisementData
Hi, We're receiving data via centralManager.centralManager.scanForPeripherals, with no options or filtering (for now), and in the func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) callback, we get advertisementData for each bluetooth device found. But, I know one of my BLE devices is sending an Eddystone TLM payload, which generally is received into the kCBAdvDataServiceData part of the advertisementData dictionary, but, it doesn't show up. What is happening however (when comparing to other devices that do show that payload), is I've noticed the "isConnectable" part is false, and others have it true. Technically we're not "connecting" as such as we're simply reading passive advertisement data, but does that have any bearing on how CoreBluetooth decides to build up it's AdvertisementData response? Example (with serviceData; and I know this has Eddystone TLM) ["kCBAdvDataLocalName": FSC-BP105N, "kCBAdvDataRxPrimaryPHY": 1, "kCBAdvDataServiceUUIDs": <__NSArrayM 0x300b71f80>( FEAA, FEF5 ) , "kCBAdvDataTimestamp": 773270526.26279, "kCBAdvDataServiceData": { FFF0 = {length = 11, bytes = 0x36021892dc0d3015aeb164}; FEAA = {length = 14, bytes = 0x20000be680000339ffa229bbce8a}; }, "kCBAdvDataRxSecondaryPHY": 0, "kCBAdvDataIsConnectable": 1] Vs This also has Eddystone TLM configured ["kCBAdvDataLocalName": 100FA9FD-7000-1000, "kCBAdvDataIsConnectable": 0, "kCBAdvDataRxPrimaryPHY": 1, "kCBAdvDataRxSecondaryPHY": 0, "kCBAdvDataTimestamp": 773270918.97273] Any insight would be great to understand if the presence of other flags drive the exposure of ServiceData or not...
0
0
84
Jul ’25
AccesorySetupKit - device not found when ManufacturerData is present
Hello, I am working on a application that connects to a peripheral using AccessorySetupKit. Peripheral is currently advertising it's custom service UUID. With this setup I am able to discover and connect to the device without issues. Firmware team wants to introduce a change and add a "manufacturer data" to the advertisment for better recognition. Upon testing with iOS app, it turns out that current code breaks and does not discover the device anymore. I am unable to configure AccessorySetupKit to be able to discover the device when it has both service uuid and manufacturer data in advertisment. Removing the newly added manufacturer data "fixes" the issue and app is able to discover peripherals again. Looking at the documentation of ASDiscoveryDescriptor it does not specify that those are mutually excluding fields nor does it provide any insight how the configured fields are evaluated against each other. Is this a bug in AccessorySetupKit? Is there a way to update the descriptor in a way that application will still be able to discover the peripheral if only service UUID is provided? Thanks in advance
4
0
122
Jul ’25
VisionOS-The prompt to use Bluetooth does not appear app developed by Unity6 with metal rendering
I am developing a VisioPro application that requires Bluetooth function and needs to receive signals from external devices via Bluetooth in Unity6 with "Metal Rendering with Compositor Services".I have supplemented my info.plist file with the following line: Privacy-BluetoothAlwaysUsageDescription Uses BLE to communicate with devices. Despite this, when I launch the app on VisionPro, the prompt to use Bluetooth does not appear. What could be the issue? What additional settings do I need to configure to enable Bluetooth usage?
3
0
64
Jul ’25
Terrible performance on iPad 11th BLE attribute notification messages.
We've been developing an iOS app in Swift for several years that run on iPad tablets in which our proprietary device emits EEG signals via BLE to the app running on the iPad tablet. The device emits the data as BLE notification messages in which the MTU is set to the maximum size that is allowed between our device and the iPad. Our device when communicating with the app running on a 10th generation iPad running iOS 18.5 it takes less than 200ms to transmit an interval of EEG signals which occurs at 500ms. Under the same conditions same version of iOS & app and the same device but using an iPad 11th generation, it takes anywhere from 800ms to 1.1 seconds (4x to 5x) to transmit an interval. Our device transmits the EEG signal using several ATT notification messages using the maximum MTU size. We are perplexed about such a huge step down in performance when running on the iPad 11th generation tablets. iPad generation Chipset Firmware -------------------------------------------------------------- 10th BCM_4387 22.5.614.3457 11th SRS_7923 HCI Rev. 2504 sub. 5003 We know that the 10th generation iPad used chipset manufactured by Broadcom. Whereas the iPad 11th generation that we've received uses a SRS chipset in which I'm unfamiliar with that chipset's manufacturer. We question if this performance degradation is due from the chipset manufacturer, the firmware revision when using attribute notifications messages over BLE in such a context. Using PacketLogger as to log the communication between the iPad tablets and our device and after analysis we haven't found anything that identifies difference in configuration settings that are exchanged between our device and iPad tablets that account for this performance degradation. Fortunately, our device is designed to work in complex environments & contexts and thus it has mechanisms accounting for transmission delays and interferences. I'd appreciate if any other Apple Developer or Apple staff is aware of the degradation when transmitting BLE attribute notification messages with the newer Apple devices using this series of chipset. If so, then: Are there any recommendations of solutions to improve this latency? Is this is being addressed for iPad 11th generation tablets? Regards, Steven Belbin Principal Developer at NeuroServo Inc.
0
0
78
Jul ’25
CarKeySewssion
CarKeySession stays in the foreground with no BLE connection and disconnection events passthrough to the App! Here is my code: public func remoteControlSession(_ session: CarKeyRemoteControlSession, vehicleDidUpdateReport: VehicleReport) { Log.i(tag: "carKeySession", "vehicle connect state: (vehicleDidUpdateReport.isConnected)") Log.i(tag: "carKeySession", "vehicle identifier: (vehicleDidUpdateReport.identifier.lowercased()), (self.vehicleIdentifier.lowercased())") } } I don't know why it was not called. And the method which is "func remoteControlSession(_ session: CarKeyRemoteControlSession, didReceivePassthroughData: Data, fromVehicle vehicleID: String)" can work well!
0
0
166
Jun ’25
Behavior differences when using CBCentralManager on different iPhone configurations
Hi, I am developing an app that checks if Bluetooth is available on the device or not (does not actually use any Bluetooth capabilities). The only CoreBluetooth API's that I use are: CBCentralManager the state property of the CBCentralManager centralManagerDidUpdateState When I am testing, I experience different behaviors on my test devices. On an iPhone 15 iOS 18.5, the app works fine. However, on an iPhone 13 iOS 18.3.2, the app crashes with the following error: This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSBluetoothAlwaysUsageDescription key with a string value explaining to the user how the app uses this data. Why is this permission required on my iPhone 13 iOS 18.3.2, but not my iPhone 15 iOS 18.5? Why do I experience different behavior on different iPhone configurations?
3
0
95
Jun ’25
Evolution of HealthKit workout API on iOS 26 and iPadOS 26 - HKLiveWorkoutDataSource and built-in Sensor Support
I am very happy to see that HealthKit with OS26 is bringing HKLiveWorkoutDataSource to iOS and iPadOS. I have been replicating a similar type for the last several years for users that only have an iPhone. I did notice that the data types that the different platform data sources collect automatically is different. That makes sense if you think exclusively about what the device can actually capture. Bluetooth HRM is the only Bluetooth SIG profile that is out-of-the-box supported for Apple Health on iOS and iPadOS (right?). Whereas watchOS 10 got all of the cycling sensors (woohoo!). It would be great if the types to collect were the same across platforms even if the device couldn't collect the data now, because then in the future when / if new sensor support is added, it will be transparent to developers. Fantastic. Easier life as an indie / third party developer. At least that is the idea. And yes, I know I can also write Core Bluetooth code and roll my own SIG implementation for the cycling profiles, but Apple already has this code in one os, 'just copy it, it will be easy'. I know that isn't the reality especially against the new ASK framework, but one can hope and dream right? Imagine how many more apps would contribute that data if it was supported out of the box. An alternative, GitHub is a great place for Apple to share their Core Bluetooth implementation of the SIG profiles :). Just another thought. Here are some feedbacks related to this: FB17931751 - HealthKit: Add built-in support for cycling sensors on iOS and iPadOS - copy paste the code from watchOS. It will be easy they said (June 2025) FB12323089 - CoreBluetooth / Health / Bluetooth Settings: Add support for cycling sensors announced in watchOS 10 to iOS and iPadOS 17 (June 2023) FB14311218 - HealthKit: Expected outdoor cycling to include .cyclingSpeed quantity type as a default HKLiveWorkoutDataSource type to collect (July 2024) FB14978701 - Bluetooth / HealthKit / Fitness: Expose information about the user specified for Apple Watch paired Cycing Speed Sensor like isConnected and wheelCircumference values (August 2024) FB18402258 - HealthKit: HKLiveWorkoutDataSource should collect same types on iOS and watchOS even if device cannot produce data today (June 2025) FB14236080 - Developer Documentation / HealthKit: Update documentation for HKLiveWorkoutDataSource typesToCollect for which sample types are automatically collected by watchOS 10 and 11 (July 2024) Tangentially related: FB10281304 - HealthKit: Add HKActivityTypes canoeBikeRun and kayakBikeRun (June 2022) FB10281349 - HealthKit: Add HKActivityType walkCanoeWalk and walkKayakWalk (June 2022) FB7807993 - Add HKQuantityTypeIdentifier.paddleDistance for canoeing, kayaking, etc type workouts (June 2020) FB12508654 - HealthKit / Settings / Bluetooth / Workouts: Cycling sensor support doesn't allow for 'bike selection' in use case of multiple bikes and multiple sensors (borrow a bike to ride together) - production usability issue (July 2023)
0
2
114
Jun ’25