{"id":32109953,"url":"https://github.com/troystribling/bluecap","last_synced_at":"2025-10-20T13:47:51.646Z","repository":{"id":17662595,"uuid":"20467219","full_name":"troystribling/BlueCap","owner":"troystribling","description":"iOS Bluetooth LE framework","archived":false,"fork":false,"pushed_at":"2023-02-10T17:28:42.000Z","size":6911,"stargazers_count":713,"open_issues_count":12,"forks_count":112,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-10-20T13:47:39.292Z","etag":null,"topics":["bluetooth-beacons","bluetooth-low-energy","carthage","centralmanager","cocoapods","corebluetooth","deserialization","futures","gatt-profile","peripheralmanager","peripherals","serdes","serialization","swift","swift-framework"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/troystribling.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2014-06-04T02:18:50.000Z","updated_at":"2025-10-03T22:18:20.000Z","dependencies_parsed_at":"2024-01-02T20:58:12.360Z","dependency_job_id":"e0f99299-86c9-4a0d-95a3-c0afdcd75d81","html_url":"https://github.com/troystribling/BlueCap","commit_stats":{"total_commits":1429,"total_committers":11,"mean_commits":129.9090909090909,"dds":"0.016095171448565426","last_synced_commit":"2cd59826966d991d36e9d2997e3ade9f8bacd03e"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/troystribling/BlueCap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troystribling%2FBlueCap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troystribling%2FBlueCap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troystribling%2FBlueCap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troystribling%2FBlueCap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/troystribling","download_url":"https://codeload.github.com/troystribling/BlueCap/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troystribling%2FBlueCap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280102711,"owners_count":26272390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-20T02:00:06.978Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bluetooth-beacons","bluetooth-low-energy","carthage","centralmanager","cocoapods","corebluetooth","deserialization","futures","gatt-profile","peripheralmanager","peripherals","serdes","serialization","swift","swift-framework"],"created_at":"2025-10-20T13:47:49.562Z","updated_at":"2025-10-20T13:47:51.639Z","avatar_url":"https://github.com/troystribling.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/troystribling/BlueCap.svg?branch=master)](https://travis-ci.org/troystribling/BlueCap)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/BlueCapKit.svg)](https://img.shields.io/cocoapods/v/BlueCapKit.svg)\n[![Platform](https://img.shields.io/cocoapods/p/BlueCapKit.svg?style=flat)](http://cocoadocs.org/docsets/BlueCapKit)\n[![License](https://img.shields.io/cocoapods/l/BlueCapKit.svg?style=flat)](http://cocoadocs.org/docsets/BlueCapKit)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n\n[![BlueCap: Swifter CoreBluetooth](https://rawgit.com/troystribling/BlueCap/6de55eaf194f101d690ba7c2d0e8b20051fd8299/Assets/banner.png)](https://itunes.apple.com/us/app/bluecap/id931219725?mt=8#)\n\n# Features\n\n- A [futures](https://github.com/troystribling/SimpleFutures) interface replacing protocol implementations.\n- Timeout for `Peripheral` connection, `Service` scan, `Service` + `Characteristic` discovery and `Characteristic` read/write.\n- A DSL for specification of GATT profiles.\n- Characteristic profile types encapsulating serialization and deserialization.\n- [Example](/Examples) applications implementing CentralManager and PeripheralManager.\n- A full featured extendable scanner and Peripheral simulator available in the [App Store](https://itunes.apple.com/us/app/bluecap/id931219725?mt=8#).\n- Thread safe.\n- Comprehensive test coverage.\n\n# Requirements\n\n- iOS 12.0+\n- Xcode 11.3.1\n\n# Installation\n\n## CocoaPods\n\n[CocoaPods](https://cocoapods.org) is an Xcode dependency manager. It is installed with the following command,\n\n```bash\ngem install cocoapods\n```\n\n\u003e Requires CocoaPods 1.1+\n\nAdd `BluCapKit` to your to your project `Podfile`,\n\n```ruby\nplatform :ios, '10.0'\nuse_frameworks!\n\ntarget 'Your Target Name' do\n  pod 'BlueCapKit', '~\u003e 0.7'\nend\n```\n\nTo enable `DBUG` output add this [`post_install` hook](https://gist.github.com/troystribling/2d4630200d3dd4e3fc8b6d5e14e4732a) to your `Podfile`\n\n## Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager for Xcode projects.\nIt can be installed using [Homebrew](http://brew.sh/),\n\n```bash\nbrew update\nbrew install carthage\n```\n\nTo add `BlueCapKit` to your `Cartfile`\n\n```ogdl\ngithub \"troystribling/BlueCap\" ~\u003e 0.7\n```\n\nTo download and build `BlueCapKit.framework` run the command,\n\n```bash\ncarthage update\n```\n\nthen add `BlueCapKit.framework` to your project.\n\nIf desired use the `--no-build` option,\n\n```bash\ncarthage update --no-build\n```\n\nThis will only download `BlueCapKit`. Then follow the steps in [Manual](#manual) to add it to a project.\n\n## \u003ca name=\"manual\"\u003eManual\u003c/a\u003e\n\n1. Place the BlueCap somewhere in your project directory. You can either copy it or add it as a git submodule.\n2. Open the BlueCap project folder and drag BlueCapKit.xcodeproj into the project navigator of your applications Xcode project.\n3. Under your Projects *Info* tab set the *iOS Deployment Target* to 9.0 and verify that the BlueCapKit.xcodeproj *iOS Deployment Target* is also 9.0.\n4. Under the *General* tab for your project target add the top BlueCapKit.framework as an *Embedded Binary*.\n5. Under the *Build Phases* tab add BlueCapKit.framework as a *Target Dependency* and under *Link Binary With Libraries* add CoreLocation.framework and CoreBluetooth.framework.\n\n# Getting Started\n\nWith BlueCap it is possible to easily implement `CentralManager` and `PeripheralManager` applications, serialize and deserialize messages exchanged with Bluetooth devices and define reusable GATT profile definitions. The BlueCap asynchronous interface uses [Futures](https://github.com/troystribling/SimpleFutures) instead of the usual block interface or the protocol-delegate pattern. Futures can be chained with the result of the previous passed as input to the next. This simplifies application implementation because the persistence of state between asynchronous calls is eliminated and code will not be distributed over multiple files, which is the case for protocol-delegate, or be deeply nested, which is the case for block interfaces. In this section a brief overview of how an application is constructed will be given.  [Following sections](#usage) will describe supported use cases. [Example applications](/Examples) are also available.\n\n## CentralManager\n\nA simple CentralManager implementation that scans for Peripherals advertising a [TiSensorTag Accelerometer Service](/BlueCapKit/Service%20Profile%20Definitions/TISensorTagServiceProfiles.swift#L16-216), connects on peripheral discovery, discovers service and characteristics and subscribes to accelerometer data updates will be described.\n\nAll applications begin by calling `CentralManager#whenStateChanges`.\n\n```swift\nlet manager = CentralManager(options: [CBCentralManagerOptionRestoreIdentifierKey : \"us.gnos.BlueCap.central-manager-documentation\" as NSString])\n\nlet stateChangeFuture = manager.whenStateChanges()\n```\n\nTo start scanning for `Peripherals` advertising the [TiSensorTag Accelerometer Service](/BlueCapKit/Service%20Profile%20Definitions/TISensorTagServiceProfiles.swift#L16-218) follow `whenStateChanges()` with `CentralManager#startScanning` and combine the two with the [SimpleFutures](https://github.com/troystribling/SimpleFutures) `FutureStream#flatMap` combinator. An application error object is also defined,\n\n```swift\npublic enum AppError : Error {\n    case invalidState\n    case resetting\n    case poweredOff\n    case unknown\n    case unlikely\n}\n\nlet serviceUUID = CBUUID(string: TISensorTag.AccelerometerService.uuid)\n\nlet scanFuture = stateChangeFuture.flatMap { [weak manager] state -\u003e FutureStream\u003cPeripheral\u003e in\n    guard let manager = manager else {\n        throw AppError.unlikely\n    }\n    switch state {\n    case .poweredOn:\n        return manager.startScanning(forServiceUUIDs: [serviceUUID])\n    case .poweredOff:\n        throw AppError.poweredOff\n    case .unauthorized, .unsupported:\n        throw AppError.invalidState\n    case .resetting:\n        throw AppError.resetting\n    case .unknown:\n        throw AppError.unknown\n    }\n}\n\nscanFuture.onFailure { [weak manager] error in\n    guard let appError = error as? AppError else {\n        return\n    }\n    switch appError {\n    case .invalidState:\n\tbreak\n    case .resetting:\n        manager?.reset()\n    case .poweredOff:\n        break\n    case .unknown:\n        break\n    }\n}\n\n```\n\nHere when `.poweredOn` is received the scan is started. On all other state changes the appropriate error is `thrown` and handled in the error handler.\n\nTo connect discovered peripherals the scan is followed by `Peripheral#connect` and combined with `FutureStream#flatMap`,\n\n```swift\nvar peripheral: Peripheral?\n\nlet connectionFuture = scanFuture.flatMap { [weak manager] discoveredPeripheral  -\u003e FutureStream\u003cVoid\u003e in\n    manager?.stopScanning()\n    peripheral = discoveredPeripheral\n    return peripheral.connect(connectionTimeout: 10.0)\n}\n```\n\nHere the scan is also stopped after a peripheral with the desired service UUID is discovered.\n\nThe `Peripheral` `Services` and `Characteristics` need to be discovered and the connection errors need to be handled. `Service` and `Characteristic` discovery are performed by 'Peripheral#discoverServices' and `Service#discoverCharacteristics` and more errors are added to `AppError`.\n\n```swift\npublic enum AppError : Error {\n    case dataCharactertisticNotFound\n    case enabledCharactertisticNotFound\n    case updateCharactertisticNotFound\n    case serviceNotFound\n    case invalidState\n    case resetting\n    case poweredOff\n    case unknown\n    case unlikely\n}\n\nlet discoveryFuture = connectionFuture.flatMap { [weak peripheral] () -\u003e Future\u003cVoid\u003e in\n    guard let peripheral = peripheral else {\n        throw AppError.unlikely\n    }\n    return peripheral.discoverServices([serviceUUID])\n}.flatMap { [weak peripheral] () -\u003e Future\u003cVoid\u003e in\n    guard let peripheral = peripheral, let service = peripheral.services(withUUID: serviceUUID)?.first else {\n        throw AppError.serviceNotFound\n    }\n    return service.discoverCharacteristics([dataUUID, enabledUUID, updatePeriodUUID])\n}\n\ndiscoveryFuture.onFailure { [weak peripheral] error in\n    switch error {\n    case PeripheralError.disconnected:\n        peripheral?.reconnect()\n    case AppError.serviceNotFound:\n        break\n    default:\n\tbreak\n    }\n}\n```\n\nHere a reconnect attempt is made if the `Peripheral` is disconnected and the `AppError.serviceNotFound` error is handled. Finally read and subscribe to the data `Characteristic` and handle the `dataCharactertisticNotFound`.\n\n```swift\npublic enum AppError : Error {\n    case dataCharactertisticNotFound\n    case enabledCharactertisticNotFound\n    case updateCharactertisticNotFound\n    case serviceNotFound\n    case invalidState\n    case resetting\n    case poweredOff\n    case unknown\n}\n\nvar accelerometerDataCharacteristic: Characteristic?\n\nlet subscriptionFuture = discoveryFuture.flatMap { [weak peripheral] () -\u003e Future\u003cVoid\u003e in\n   guard let peripheral = peripheral, let service = peripheral.services(withUUID: serviceUUID)?.first else {\n        throw AppError.serviceNotFound\n    }\n    guard let dataCharacteristic = service.service.characteristics(withUUID: dataUUID)?.first else {\n        throw AppError.dataCharactertisticNotFound\n    }\n    accelerometerDataCharacteristic = dataCharacteristic\n    return dataCharacteristic.read(timeout: 10.0)\n}.flatMap { [weak accelerometerDataCharacteristic] () -\u003e Future\u003cVoid\u003e in\n    guard let accelerometerDataCharacteristic = accelerometerDataCharacteristic else {\n        throw AppError.dataCharactertisticNotFound\n    }\n    return accelerometerDataCharacteristic.startNotifying()\n}.flatMap { [weak accelerometerDataCharacteristic] () -\u003e FutureStream\u003cData?\u003e in\n    guard let accelerometerDataCharacteristic = accelerometerDataCharacteristic else {\n        throw AppError.dataCharactertisticNotFound\n    }\n    return accelerometerDataCharacteristic.receiveNotificationUpdates(capacity: 10)\n}\n\ndataUpdateFuture.onFailure { [weak peripheral] error in\n    switch error {\n    case PeripheralError.disconnected:\n        peripheral?.reconnect()\n    case AppError.serviceNotFound:\n        break\n    case AppError.dataCharactertisticNotFound:\n\tbreak\n    default:\n\tbreak\n    }\n}\n```\n\nThese examples can be written as a single `flatMap` chain as shown in the  [CentralManager Example](/Examples/CentralManager).\n\n## PeripheralManager\n\nA simple `PeripheralManager` application that emulates a [TiSensorTag Accelerometer Service](/BlueCapKit/Service%20Profile%20Definitions/TISensorTagServiceProfiles.swift#L16-218) supporting all `Characteristics` will be described. It will advertise the service and respond to characteristic write requests on the writable `Characteristics`.\n\nFirst the `Characteristics` and `Service` are created and the `Characteristics` are then added to `Service`\n\n```swift\n// create accelerometer service\nlet accelerometerService = MutableService(uuid: TISensorTag.AccelerometerService.uuid)\n\n// create accelerometer data characteristic\nlet accelerometerDataCharacteristic = MutableCharacteristic(profile: RawArrayCharacteristicProfile\u003cTISensorTag.AccelerometerService.Data\u003e())\n\n// create accelerometer enabled characteristic\nlet accelerometerEnabledCharacteristic = MutableCharacteristic(profile: RawCharacteristicProfile\u003cTISensorTag.AccelerometerService.Enabled\u003e())\n\n// create accelerometer update period characteristic\nlet accelerometerUpdatePeriodCharacteristic = MutableCharacteristic(profile: RawCharacteristicProfile\u003cTISensorTag.AccelerometerService.UpdatePeriod\u003e())\n\n// add characteristics to service\naccelerometerService.characteristics = [accelerometerDataCharacteristic, accelerometerEnabledCharacteristic, accelerometerUpdatePeriodCharacteristic]\n```\n\nNext create the `PeripheralManager` add the `Service` and start advertising.\n\n```swift\nenum AppError: Error {\n    case invalidState\n    case resetting\n    case poweredOff\n    case unsupported\n    case unlikely\n}\n\nlet manager = PeripheralManager(options: [CBPeripheralManagerOptionRestoreIdentifierKey : \"us.gnos.BlueCap.peripheral-manager-documentation\" as NSString])\n\nlet startAdvertiseFuture = manager.whenStateChanges().flatMap { [weak manager] state -\u003e Future\u003cVoid\u003e in\n    guard let manager = manager else {\n        throw AppError.unlikely\n    }\n    switch state {\n    case .poweredOn:\n        manager.removeAllServices()\n        return manager.add(self.accelerometerService)\n    case .poweredOff:\n        throw AppError.poweredOff\n    case .unauthorized, .unknown:\n        throw AppError.invalidState\n    case .unsupported:\n        throw AppError.unsupported\n    case .resetting:\n        throw AppError.resetting\n    }\n}.flatMap { [weak manager] _ -\u003e Future\u003cVoid\u003e in\n    guard let manager = manager else {\n        throw AppError.unlikely\n    }\n    manager.startAdvertising(TISensorTag.AccelerometerService.name, uuids:[CBUUID(string: TISensorTag.AccelerometerService.uuid)])\n}\n\nstartAdvertiseFuture.onFailure { [weak manager] error in\n    switch error {\n    case AppError.poweredOff:\n        manager?.reset()            \n    case AppError.resetting:\n        manager?.reset()\n    default:\n\tbreak\n    }\n    manager?.stopAdvertising()\n}\n```\n\nNow respond to write events on `accelerometerEnabledFuture` and `accelerometerUpdatePeriodFuture`.\n\n```swift\n// respond to Update Period write requests\nlet accelerometerUpdatePeriodFuture = startAdvertiseFuture.flatMap {\n    accelerometerUpdatePeriodCharacteristic.startRespondingToWriteRequests()\n}\n\naccelerometerUpdatePeriodFuture.onSuccess {  [weak accelerometerUpdatePeriodCharacteristic] (request, _) in\n    guard let accelerometerUpdatePeriodCharacteristic = accelerometerUpdatePeriodCharacteristic else {\n        throw AppError.unlikely\n    }\n    guard let value = request.value, value.count \u003e 0 \u0026\u0026 value.count \u003c= 8 else {\n        return\n    }\n    accelerometerUpdatePeriodCharacteristic.value = value\n    accelerometerUpdatePeriodCharacteristic.respondToRequest(request, withResult:CBATTError.success)\n}\n\n// respond to Enabled write requests\nlet accelerometerEnabledFuture = startAdvertiseFuture.flatMap {\n    accelerometerEnabledCharacteristic.startRespondingToWriteRequests(capacity: 2)\n}\n\naccelerometerEnabledFuture.onSuccess { [weak accelerometerUpdatePeriodCharacteristic] (request, _) in\n    guard let accelerometerEnabledCharacteristic = accelerometerEnabledCharacteristic else {\n        throw AppError.unlikely\n    }\n    guard let value = request.value, value.count == 1 else {\n        return\n    }\n    accelerometerEnabledCharacteristic.value = request.value\n    accelerometerEnabledCharacteristic.respondToRequest(request, withResult:CBATTError.success)\n}\n```\n\nSee [PeripheralManager Example](/Examples/PeripheralManager) for details.\n\n## Test Cases\n\n[Test Cases](/Tests) are available. To run type,\n\n```bash\npod install\n```\n\nand run from test tab in generated `workspace`.\n\n## Examples\n\n[Examples](/Examples) are available that implement both CentralManager and PeripheralManager. The [BluCap](https://itunes.apple.com/us/app/bluecap/id931219725?mt=8#) app is also available. The example projects are constructed using either [CocoaPods](https://cocoapods.org) or [Carthage](https://github.com/Carthage/Carthage). The CocaPods projects require installing the Pod before building,\n\n```bash\npod install\n```\n\nand Carthage projects require,\n\n```bash\ncarthage update\n```\n\n\u003ctable\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/BlueCap\"\u003eBlueCap\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003eBlueCap provides CentralManager, PeripheralManager and iBeacon Ranging with implementations of GATT profiles. In CentralManager mode a scanner for Bluetooth LE peripherals is provided. In PeripheralManager mode an emulation of any of the included GATT profiles or an iBeacon is supported. In iBeacon Ranging mode beacon regions can be configured and monitored.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/CentralManager\"\u003eCentralManager\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003eCentralManager implements a BLE CentralManager scanning for services advertising the TiSensorTag Accelerometer Service. When a Peripheral is discovered a connection is established, services are discovered, the accelerometer is enabled and the application subscribes to accelerometer data updates. It is also possible to change the data update period.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/CentralManagerWithProfile\"\u003eCentralManagerWithProfile\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003eA version of CentralManager that uses GATT Profile Definitions to create services.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/PeripheralManager\"\u003ePeripheralManager\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003ePeripheralManager implements a BLE PeripheralManager advertising a TiSensorTag Accelerometer Service. PeripheralManager uses the onboard accelerometer to provide data updates.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"Examples/PeripheralManagerWithProfile\"\u003ePeripheralManagerWithProfile\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003eA version of Peripheral that uses GATT Profile Definitions to create services.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/Beacon\"\u003eBeacon\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003ePeripheral emulating an iBeacon.\u003c/td\u003e\n\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003ca href=\"/Examples/Beacons\"\u003eBeacons\u003c/a\u003e\u003c/td\u003e\n\t\t\u003ctd\u003eiBeacon ranging.\u003c/td\u003e\n\t\u003c/tr\u003e\n\n\n\u003c/table\u003e\n\n# \u003ca name=\"usage\"\u003eDocumentation\u003c/a\u003e\n\nBlueCap supports many features that simplify writing Bluetooth LE applications. Use cases with example implementations are described in each of the following sections.\n\n1. [CentralManager](/Documentation/CentralManager.md): The BlueCap CentralManager implementation replaces [CBCentralManagerDelegate](https://developer.apple.com/library/prerelease/ios/documentation/CoreBluetooth/Reference/CBCentralManagerDelegate_Protocol/index.html#//apple_ref/occ/intf/CBCentralManagerDelegate) and [CBPeripheralDelegate](https://developer.apple.com/library/prerelease/ios/documentation/CoreBluetooth/Reference/CBPeripheralDelegate_Protocol/index.html#//apple_ref/occ/intf/CBPeripheralDelegate) protocol implementations with a Scala Futures interface using [SimpleFutures](https://github.com/troystribling/SimpleFutures).\n\n2. [PeripheralManager](/Documentation/PeripheralManager.md): The BlueCap PeripheralManager implementation replaces [CBPeripheralManagerDelegate](https://developer.apple.com/library/prerelease/ios/documentation/CoreBluetooth/Reference/CBPeripheralManagerDelegate_Protocol/index.html#//apple_ref/occ/intf/CBPeripheralManagerDelegate) protocol implementations with a Scala Futures interface using [SimpleFutures](https://github.com/troystribling/SimpleFutures).\n\n3. [Serialization/Deserialization](/Documentation/SerializationDeserialization.md): Serialization and deserialization of device messages.\n\n4. [GATT Profile Definition](/Documentation/GATTProfileDefinition.md): Define reusable GATT profiles and add profiles to the BlueCap app.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftroystribling%2Fbluecap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftroystribling%2Fbluecap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftroystribling%2Fbluecap/lists"}