{"id":1198,"url":"https://github.com/AntonTheDev/ExtendaBLE","last_synced_at":"2025-07-30T20:32:49.336Z","repository":{"id":56910189,"uuid":"86771313","full_name":"AntonTheDev/ExtendaBLE","owner":"AntonTheDev","description":"Blocks Based Bluetooth LE Connectivity framework for iOS/watchOS/tvOS/OSX. Quickly configure centrals \u0026 peripherals, perform read/write operations, and respond characteristic updates.","archived":false,"fork":false,"pushed_at":"2017-11-15T17:04:10.000Z","size":296,"stargazers_count":101,"open_issues_count":1,"forks_count":5,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-30T20:51:44.754Z","etag":null,"topics":["ble","bluetooth","bluetooth-le","bluetooth-low-energy","ios","osx","swift","tvos","watchos"],"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/AntonTheDev.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}},"created_at":"2017-03-31T02:52:31.000Z","updated_at":"2024-04-25T15:49:08.000Z","dependencies_parsed_at":"2022-08-21T04:20:32.562Z","dependency_job_id":null,"html_url":"https://github.com/AntonTheDev/ExtendaBLE","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonTheDev%2FExtendaBLE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonTheDev%2FExtendaBLE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonTheDev%2FExtendaBLE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonTheDev%2FExtendaBLE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AntonTheDev","download_url":"https://codeload.github.com/AntonTheDev/ExtendaBLE/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228187565,"owners_count":17882326,"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","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":["ble","bluetooth","bluetooth-le","bluetooth-low-energy","ios","osx","swift","tvos","watchos"],"created_at":"2024-01-05T20:15:41.068Z","updated_at":"2024-12-04T20:31:05.886Z","avatar_url":"https://github.com/AntonTheDev.png","language":"Swift","funding_links":[],"categories":["Hardware"],"sub_categories":["Bluetooth","Other free courses"],"readme":"# ExtendaBLE\n[![Cocoapods Compatible](https://img.shields.io/badge/pod-v0.4-blue.svg)]()\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)]()\n[![Build Status](https://travis-ci.org/AntonTheDev/ExtendaBLE.svg?branch=master)](https://travis-ci.org/AntonTheDev/ExtendaBLE)\n[![Platform](https://img.shields.io/badge/platform-iOS%20|%20tvOS%20|%20watchOS%20|%20OSX-lightgrey.svg)]()\n[![License](https://img.shields.io/badge/license-MIT-343434.svg)](/LICENSE.md)\n\n![alt tag](/Documentation/extendable_header.png?raw=true)\n\n## Introduction\n\n**ExtendaBLE** provides a very flexible syntax for defining centrals and peripherals with ease. Following a blocks based builder approach you can easily create centrals, peripherals, associated services, characteristics, and define callbacks to listen for characteristic changes accordingly.\n\nOne of the unique features of **ExtendaBLE** is that it allows to bypass the limitations of the MTU size in communicating between devices. The library negotiates a common MTU size, and allows breaks down the data to be sent between devices into packets, which are then reconstructed by the receiving entity.\n\nAn Android library is in the works with support for packet based communication between iOS /tvOs/OSX. **ExtendaBLE-Android**, a work in progress can be found here..\n\n[ExtendaBLE-Android](https://github.com/AntonTheDev/ExtendaBLE-Android)\n\n## Features\n\n- [x] Blocks Syntax for Building Centrals and Peripherals\n- [x] Callbacks for responding to, read and write, characteristic changes\n- [x] Packet Based Payload transfer using negotiated MTU sizes\n- [x] Characteristic Update Callbacks\n- [x] Streamlined parsing for characteristic read operations\n\n## Installation\n\n* **Requirements** : XCode 9.0+, iOS 9.0+, tvOS 9.0+, OSX 10.10+\n* [Installation Instructions](/Documentation/installation.md)\n* [Release Notes](/Documentation/release_notes.md)\n\n## Communication\n\n- If you **found a bug**, or **have a feature request**, open an issue.\n- If you **need help** or a **general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/extenda-ble). (tag 'extenda-ble')\n- If you **want to contribute**, review the [Contribution Guidelines](/Documentation/CONTRIBUTING.md), and submit a pull request.\n\n## Basic Setup\n\nIn configuring BLE the first step is to configure a unique UUID for the shared a for the service(s) and characteristic(s) to intercommunicate between the peripheral \u0026 central.\n\nFor the purposes of documentation, the following constants will be shared across the configuration examples\n\n```swift\nlet dataServiceUUIDKey                  = \"3C215EBB-D3EF-4D7E-8E00-A700DFD6E9EF\"\nlet dataServiceCharacteristicUUIDKey    = \"830FEB83-C879-4B14-92E0-DF8CCDDD8D8F\"\n```\n\nIf you are not familiar with how BLE works, please review the [Core Bluetooth Programming Guide](https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html) before continuing.\n\n### Peripheral Manager\n\nIn it's simplest form, the following is an example of how to configure peripheral using a simple blocks based syntax.\n\n```swift\nperipheral = ExtendaBLE.newPeripheralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) { (service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write]).permissions([.readable, .writeable])\n        }\n    }\n}\n```\n\n#### Begin Advertising\n\nTo start advertising services and their respective characteristics, just call on ``startAdvertising()`` on the peripheral created in the prior section.\n\n```swift\nperipheral?.startAdvertising()\n```\n\n#### Responding to Updates\n\nIf you would like to respond to characteristic updates on the peripheral when a central updates a value, define an ``onUpdate  { (data, error) in }`` per characteristic accordingly. When the Central finishes updating the value, the callback will be triggered.\n\n```swift\nperipheral = ExtendaBLE.newPeripheralManager { (manager) in\n    manager.addService(dataServiceUUIDKey) { (service) in\n\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write, .notify]).permissions([.readable, .writeable])                \n\n            characteristic.onUpdate { (data, error) in\n                /* Called whenever the value is updated by the CENTRAL */\n            }\n        }\n    }\n}\n```\n\n#### Notifying Central\n\nIf you would like the peripheral to retain a connection for a specific characteristic, and notify the connected central manager when the value is updated, when configuring the properties, ensure to include the ``.notify`` CBCharacteristicProperty in the definition as follows.\n\n```swift\nperipheral = ExtendaBLE.newPeripheralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) { (service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write, .notify]).permissions([.readable, .writeable])\n        }\n    }\n}\n```\n\n### Central Manager\n\nIn it's simplest form, the following is an example of how to configure central manager using a simple blocks based syntax.\n\n```swift\ncentral = ExtendaBLE.newCentralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) {(service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write]).permissions([.readable, .writeable])\n        }\n    }\n}\n```\n\n#### Begin Scanning\n\nStart scanning for peripheral(s) defined with the services, and their respective characteristics, just call on ``startScan()`` on the central created in the prior section. The central will auto connect to the peripheral when found.\n\n```swift\ncentral?.startScan()\n```\n\n#### Responding to State Changes\n\nResponding to stages of the scanning operation, the following callbacks can be defined for the manager.\n\n```swift\ncentral = ExtendaBLE.newCentralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) {(service) in\n        /* Characteristic Definitions */\n    }.onPeripheralConnectionChange{ (connected, peripheral, error) in\n        /* Respond to Successful Connection */\n    }.onDidDiscover { (central, advertisementData, rssi) in\n        /* Respond to Discovered Services */\n    }.onStateChange { (state) in\n        /* Respond to State Changes */\n    }\n}\n```\n\n#### Respond to Successful Connection\n\nTo perform a Read/Write upon connecting to a peripheral, define a callback as follows to be notified of the successful connection.\n\n```swift\ncentral = ExtendaBLE.newCentralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) {(service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write]).permissions([.readable, .writeable])\n        }\n    }.onPeripheralConnectionChange{ (connected, peripheral, error) in\n        /* Perform Read Transaction upon connecting */\n    }\n}\n```\n\n#### Responding to Update Notification\n\nIf you would like to retain a connection for a specific characteristic, and be notified by the peripheral when the value is updated, when configuring the properties, ensure to include the ``.notify`` CBCharacteristicProperty in the definition as follows, and create a call back to respond to the change.\n\n```swift\n\ncentral = ExtendaBLE.newCentralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) {(service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write, .notify]).permissions([.readable, .writeable])\n\n            characteristic.onUpdate { (data, error) in\n                /* Called whenever the value is updated by the PERIPHERAL */\n            }\n        }\n    }\n}\n\n```\n\n#### Perform Write\n\nTo perform a write for a specific characteristic for a connected peripheral, call the ``write(..)`` on the central, and with the content to write, and the characteristicUUID to write to. The callback will be triggered once the write is complete.  \n\n```swift\ncentral?.write(data: stringData, toUUID: dataServiceCharacteristicUUIDKey) { (writtenData, error) in    \n\n    /* Do something upon successful write operation */\n}\n```\n\n#### Perform Read\n\nTo perform a read for a specific characteristic for a connected peripheral, call the ``read(..)`` on the central, and with  the characteristicUUID to read. The callback will be triggered once the read is complete with the ``Data`` read, or an error if the operation failed.\n\n```swift\ncentral?.read(characteristicUUID: dataServiceCharacteristicUUIDKey) { (returnedData, error) in\n    let valueString = String(data: returnedData!, encoding: .utf8)?\n\n    /* Do something upon successful read operation */  \n}\n```\n\n### Packet Based Communication\n\nBLE has a limitation as to how much data can be sent between devices relative to the MTU size. To enabled the ability for the central and peripheral to communicate characteristic data greater in size than this limitation, **ExtendaBLE** provides the ability to use packets to breakup and rebuild the data when communicating between devices.\n\nTo enable the ability to send data greater than the MTU limitation of BLE, set the ``packetsEnabled`` to true on both the peripheral and the central. This will ensure that when communications occurs, the data is broken up into individual packets which will be sent across and rebuilt once the operation is complete.  \n\n```swift\nperipheral = ExtendaBLE.newPeripheralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) { (service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write])\n            characteristic.permissions([.readable, .writeable])\n            characteristic.packetsEnabled(true)\n        }\n    }\n}\n\ncentral = ExtendaBLE.newCentralManager { (manager) in\n\n    manager.addService(dataServiceUUIDKey) {(service) in\n        service.addCharacteristic(dataServiceCharacteristicUUIDKey) { (characteristic) in\n            characteristic.properties([.read, .write])\n            characteristic.permissions([.readable, .writeable])     \n            characteristic.packetsEnabled(true)\n        }\n    }\n}\n```\n\n\n### Extracting Data from Byte Stream\n\nWhen communicating reading from physical peripheral, generally the specifications will return a byte stream, and will identify where different types of data are located, and it is up to the developer to extract and covert specific parts of the returned data. With **ExtendaBLE** and extension is included to easily extract data from such streams. The following methods can be called on the returned ``Data`` instance with a specified start index to extract the following types of data.\n\n```swift\npublic func int8Value(atIndex : Int) -\u003e Int8?\npublic func int16Value(atIndex : Int) -\u003e Int16?\npublic func int32Value(atIndex : Int) -\u003e Int32?\npublic func int64Value(atIndex : Int) -\u003e Int64?\npublic func uint8Value(atIndex : Int) -\u003e UInt8?\npublic func uint16Value(atIndex : Int) -\u003e UInt16?\npublic func uint32Value(atIndex : Int) -\u003e UInt32?\npublic func uint64Value(atIndex : Int) -\u003e UInt64?\npublic func stringValue(atIndex : Int) -\u003e String?\n```\n\nIf finer control is needed, ranges can be used to extract specific data from the stream as follows.\n\n```swift\npublic func int8Value(inRange range : Range\u003cData.Index\u003e) -\u003e Int8?\npublic func int16Value(inRange range : Range\u003cData.Index\u003e) -\u003e Int16?\npublic func int32Value(inRange range : Range\u003cData.Index\u003e) -\u003e Int32?\npublic func int64Value(inRange range : Range\u003cData.Index\u003e) -\u003e Int64?\npublic func uint8Value(inRange range : Range\u003cData.Index\u003e) -\u003e UInt8?\npublic func uint16Value(inRange range : Range\u003cData.Index\u003e) -\u003e UInt16?\npublic func uint32Value(inRange range : Range\u003cData.Index\u003e) -\u003e UInt32?\npublic func uint64Value(inRange range : Range\u003cData.Index\u003e) -\u003e UInt64?\npublic func doubleValue(inRange range : Range\u003cData.Index\u003e) -\u003e Double?\npublic func floatValue(inRange range : Range\u003cData.Index\u003e) -\u003e Float?\npublic func stringValue(inRange range : Range\u003cData.Index\u003e) -\u003e String?\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAntonTheDev%2FExtendaBLE","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAntonTheDev%2FExtendaBLE","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAntonTheDev%2FExtendaBLE/lists"}