Skip to content

Instantly share code, notes, and snippets.

@kevincar
Created July 8, 2021 01:25
Show Gist options
  • Save kevincar/87221fc015f8e692267c0b72bf5640c9 to your computer and use it in GitHub Desktop.
Save kevincar/87221fc015f8e692267c0b72bf5640c9 to your computer and use it in GitHub Desktop.
Python Objective-C BLE
from threading import Event
from manager import Manager
if __name__ == "__main__":
done: Event = Event()
manager: Manager = Manager.alloc().init()
manager.advertize()
done.wait()
import objc
from typing import List
from threading import Event
from Foundation import NSObject, NSError
from CoreBluetooth import (
CBUUID,
CBATTRequest,
CBCentral,
CBService,
CBCharacteristic,
CBMutableService,
CBMutableCharacteristic,
CBPeripheralManager,
CBManagerStatePoweredOff,
CBManagerStatePoweredOn,
CBManagerStateUnauthorized,
CBManagerStateUnknown,
CBManagerStateUnsupported,
CBCharacteristicPropertyIndicate,
CBCharacteristicPropertyRead,
CBCharacteristicPropertyWriteWithoutResponse,
CBAttributePermissionsReadable,
CBAttributePermissionsWriteable,
CBAdvertisementDataLocalNameKey,
CBAdvertisementDataServiceUUIDsKey,
)
from libdispatch import dispatch_queue_create, DISPATCH_QUEUE_SERIAL
class Manager(NSObject):
def init(self):
self = objc.super(Manager, self).init()
self._powered_on_event: Event = Event()
self._peripheralManager: CBPeripheralManager = (
CBPeripheralManager.alloc().initWithDelegate_queue_(
self,
dispatch_queue_create(b"itababy.corebluetooth", DISPATCH_QUEUE_SERIAL),
)
)
self._powered_on_event.wait()
self._running: bool = True
self._peripheralData: str = "ItaBaby"
self._charUUID: CBUUID = CBUUID.UUIDWithString_(
"DDCA9B49-A6F5-462F-A89A-C2144083CA7F"
)
self._myUUID: CBUUID = CBUUID.UUIDWithString_(
"BD0F6577-4A38-4D71-AF1B-4E8F57708080"
)
return self
# Method called whenever BT state changes
def peripheralManagerDidUpdateState_(self, peripheral: CBPeripheralManager):
state: int = peripheral.state()
string: str = "Uknown state"
if state == CBManagerStatePoweredOff:
string = "CoreBluetooth BLE hardware is powered off."
elif state == CBManagerStatePoweredOn:
string = "CoreBluetooth BLE hardware is powered on and ready."
self._powered_on_event.set()
elif state == CBManagerStateUnauthorized:
string = "CoreBluetooth BLE state is unauthorized."
elif state == CBManagerStateUnknown:
string = "CoreBluetooth BLE state is unknown."
elif state == CBManagerStateUnsupported:
string = "CoreBluetooth BLE hardware is unsupported on this platform."
print(string)
def advertize(self):
if self._peripheralManager.isAdvertising():
return
service: CBMutableService = CBMutableService.alloc().initWithType_primary_(
self._myUUID, True
)
myCharacteristic: CBMutableCharacteristic = (
CBMutableCharacteristic.alloc().initWithType_properties_value_permissions_(
self._charUUID,
CBCharacteristicPropertyRead
| CBCharacteristicPropertyIndicate
| CBCharacteristicPropertyWriteWithoutResponse,
None,
CBAttributePermissionsReadable | CBAttributePermissionsWriteable,
)
)
service.setCharacteristics_([myCharacteristic])
self._peripheralManager.addService_(service)
self._peripheralManager.startAdvertising_(
{
CBAdvertisementDataLocalNameKey: "ITAMAR-MAC-BOOK-PRO",
CBAdvertisementDataServiceUUIDsKey: [self._myUUID],
}
)
def peripheralManagerDidStartAdvertising_error_(
self, peripheral: CBPeripheralManager, error: NSError
):
print(f"peripheralManagerDidStartAdvertising {peripheral.description()}")
if error:
print(f"Error advertising: {error.localizedDescription()}")
def peripheralManager_didAddService_error_(
self, peripheral: CBPeripheralManager, service: CBService, error: NSError
):
print(f"peripheralManagerDidAddService: {service} {error}")
if error:
print(f"Error publishing serivce: {error.localizedDescription()}")
def peripheralManager_didReceiveReadRequest_(
self, peripheral: CBPeripheralManager, request: CBATTRequest
):
if request.characteristic().UUID().isEqual_(self._charUUID):
request.setValue_(bytes(bytearray(self._peripheralData, "UTF8")))
peripheral.respondToRequest_withResult_(request, 0)
print(
f"didReceiveReadRequest: {request.central()} "
+ f"{request.characteristic().UUID().UUIDString()}. "
+ f"Returning {self._peripheralData}"
)
else:
print(
f"didReceiveReadRequest: {request.central()} "
+ "{request.characteristic().UUID().UUIDString()}. Ignoring!"
)
def peripheralManager_didReceiveWriteRequests_(
self, peripheral: CBPeripheralManager, requests: List[CBATTRequest]
):
request: CBATTRequest = requests[0]
if request.characteristic().UUID().isEqual_(self._charUUID):
self._peripheralData = bytearray(request.value()).decode()
print(f"didReceiveWriteRequest: Wrote: {self._peripheralData}")
else:
print(
f"didReceiveWriteRequest: {request.central} "
+ f"{request.characteristic().UUID().UUIDString()}. Ignoring"
)
def peripheralManager_central_didSubscribeToCharacteristic_(
self,
peripheral: CBPeripheralManager,
central: CBCentral,
characteristic: CBCharacteristic,
):
print("didSubscribeToCharacteristic")
def running(self) -> bool:
return self._running
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment