PyObjC CoreBluetooth Framework
PyObjC provides Python bindings for Apple's macOS frameworks, allowing Python applications to interact with native macOS APIs. `pyobjc-framework-corebluetooth` specifically offers wrappers for the CoreBluetooth framework, enabling Python programs to communicate with Bluetooth Low Energy (BLE) devices. The current version is 12.1, and PyObjC typically releases new versions in sync with macOS SDK updates and Python version support changes.
Warnings
- breaking PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped support for Python 3.8. Always check the `requires_python` metadata for compatibility with your Python version.
- gotcha `pyobjc-framework-corebluetooth` is a macOS-specific library. It relies on the underlying CoreBluetooth framework provided by Apple's operating system and will not function on Windows, Linux, or other non-macOS platforms.
- breaking PyObjC 11.1 aligned the behavior of 'init' family methods (initializers) with clang's Automatic Reference Counting (ARC) documentation. These methods now correctly steal a reference to `self` and return a new reference. Code relying on previous object lifecycle assumptions for initializers might break.
- gotcha Changes in PyObjC 10.3 and 10.3.1 altered the interaction between Python's `__init__` and `__new__` methods for bridged classes. Specifically, `__init__` could not be used when the PyObjC-provided `__new__` was active, though this was partially reverted in 10.3.1 for user-implemented `__new__`.
- gotcha For console applications using PyObjC, the delegate callbacks and asynchronous events (like CoreBluetooth discoveries) require a running Cocoa event loop. Without it, delegate methods may not be called, or the program might exit prematurely.
Install
-
pip install pyobjc-framework-corebluetooth
Imports
- CBCentralManager
from CoreBluetooth import CBCentralManager
- CBPeripheral
from CoreBluetooth import CBPeripheral
- CBManagerDelegate
from CoreBluetooth import CBManagerDelegate
Quickstart
import objc
from Foundation import NSObject, NSLog
from CoreBluetooth import CBCentralManager, CBManagerDelegate
# Define a delegate for CBCentralManager
# PyObjC automatically bridges Python classes inheriting from NSObject
# and implementing a protocol into Objective-C delegates.
class MyCentralManagerDelegate(NSObject, protocols=[CBManagerDelegate]):
def init(self):
self = objc.super(MyCentralManagerDelegate, self).init()
if self is None:
return None
self.centralManager = None
return self
# This method is called when the central manager's state changes.
# It's typically the first delegate method called after initialization.
def centralManagerDidUpdateState_(self, central):
NSLog("Central Manager did update state: %d", central.state())
# The state is an enum (e.g., CBManagerStatePoweredOn (5), CBManagerStatePoweredOff (4)).
# For better readability, you'd map the enum values to human-friendly strings.
def main():
delegate = MyCentralManagerDelegate.alloc().init()
# CBCentralManager holds a weak reference to its delegate.
# Ensure the Python delegate object is not garbage collected for the duration
# of the manager's lifecycle. Keeping `delegate` in a local scope like `main`
# is sufficient for this quick example.
# Initialize the CBCentralManager, passing our delegate.
# 'None' for the queue uses the main dispatch queue.
manager = CBCentralManager.alloc().initWithDelegate_queue_options_(
delegate, None, None
)
NSLog("Initialized CBCentralManager. Waiting for state update...")
# CoreBluetooth operations are asynchronous and report via delegate methods.
# For a console application, you typically need to run a Cocoa event loop
# (e.g., using `PyObjCTools.AppHelper.runConsoleEventLoop()` from `pyobjc-tools`)
# to process callbacks. For this minimal example, we'll wait briefly to see
# the initial state update.
import time
time.sleep(1) # Give the system a moment to call the delegate
NSLog("Quickstart complete. For interactive BLE, use a proper event loop.")
if __name__ == "__main__":
main()