{"id":21928483,"url":"https://github.com/matthewelse/pygattlib","last_synced_at":"2025-04-19T17:51:17.945Z","repository":{"id":36744038,"uuid":"41050641","full_name":"matthewelse/pygattlib","owner":"matthewelse","description":"Fork of https://bitbucket.org/OscarAcena/pygattlib","archived":false,"fork":false,"pushed_at":"2018-02-20T20:00:11.000Z","size":436,"stargazers_count":12,"open_issues_count":1,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T11:11:17.757Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matthewelse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-19T17:55:10.000Z","updated_at":"2024-01-30T14:37:04.000Z","dependencies_parsed_at":"2022-09-25T02:22:38.091Z","dependency_job_id":null,"html_url":"https://github.com/matthewelse/pygattlib","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewelse%2Fpygattlib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewelse%2Fpygattlib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewelse%2Fpygattlib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewelse%2Fpygattlib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matthewelse","download_url":"https://codeload.github.com/matthewelse/pygattlib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249753083,"owners_count":21320664,"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":[],"created_at":"2024-11-28T22:26:11.018Z","updated_at":"2025-04-19T17:51:17.914Z","avatar_url":"https://github.com/matthewelse.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"Index\r\n=======\r\n\r\n* [Description](#markdown-header-description)\r\n* [Installation](#markdown-header-installation)\r\n    * [Python pip](#markdown-header-python-pip)\r\n    * [Debian way](#markdown-header-debian-way)\r\n    * [Compiling from source](#markdown-header-compiling-from-source)\r\n* [Usage](#markdown-header-usage)\r\n    * [Discovering devices](#markdown-header-discovering-devices)\r\n    * [Reading data](#markdown-header-reading-data)\r\n    * [Reading data asynchronously](#markdown-header-reading-data-asynchronously)\r\n    * [Writing data](#markdown-header-writing-data)\r\n    * [Receiving notifications](#markdown-header-receiving-notifications)\r\n* [Disclaimer](#markdown-header-disclaimer)\r\n\r\nDescription\r\n===========\r\n\r\nThis is a Python library to use the GATT Protocol for Bluetooth LE\r\ndevices. It is a wrapper around the implementation used by gatttool in\r\nbluez package. It does not call other binaries to do its job :)\r\n\r\nInstallation\r\n============\r\n\r\nThere are many ways of installing this library: using Python Pip,\r\nusing the Debian package, or manually compiling it.\r\n\r\nPython pip\r\n----------\r\n\r\nInstall as ever (you may need to install the packages listed on `DEPENDS` files):\r\n\r\n    $ sudo pip install gattlib\r\n\r\nYou can install for Python3 too, just use `pip3`\r\n\r\nDebian way\r\n----------\r\n\r\nAdd the following line to your sources list:\r\n\r\n    deb http://babel.esi.uclm.es/arco sid main\r\n\r\nAnd install using apt-get (or similar):\r\n\r\n    $ sudo apt-get update\r\n    $ sudo apt-get install python-gattlib\r\n\r\nYou can install for Python3 too (Debian package is called `python3-gattlib`).\r\n\r\nCompiling from source\r\n---------------------\r\n\r\nYou should install the needed packages, which are described on `DEPENDS`\r\nfile. Take special care about versions: libbluetooth-dev should be\r\n4.101 or greater. Then, just type:\r\n\r\n    $ make\r\n    [...]\r\n\r\nIf you want to compile for Python 3, you need to:\r\n\r\n    $ make PYTHON_VER=3\r\n\r\nThen, to install, just:\r\n\r\n    $ make install\r\n\r\nUsage\r\n=====\r\n\r\nThis library provides two ways of work: sync and async. The Bluetooth\r\nLE GATT protocol is asynchronous, so, when you need to read some\r\nvalue, you make a petition, and wait for response. From the\r\nperspective of the programmer, when you call a read method, you need\r\nto pass it a callback object, and it will return inmediatly. The\r\nresponse will be \"injected\" on that callback object.\r\n\r\nThis Python library allows you to call using a callback object\r\n(async), or without it (sync). If you does not provide a callback\r\n(working sync.), the library internally will create one, and will wait\r\nuntil a response arrives, or a timeout expires. Then, the call will\r\nreturn with the received data.\r\n\r\nDiscovering devices\r\n-------------------\r\n\r\nTo discover BLE devices, use the `DiscoveryService` provided. You need\r\nto create an instance of it, indicating the Bluetooth device you want\r\nto use. Then call the method `discover`, with a timeout. It will\r\nreturn a dictionary with the address and name of all devices that\r\nresponded the discovery.\r\n\r\n**Note**: it is very likely that you will need admin permissions to do\r\na discovery, so run this script using `sudo` (or something similar).\r\n\r\nAs example:\r\n\r\n    from gattlib import DiscoveryService\r\n\r\n    service = DiscoveryService(\"hci0\")\r\n    devices = service.discover(2)\r\n\r\n    for address, name in devices.items():\r\n        print(\"name: {}, address: {}\".format(name, address))\r\n\r\nReading data\r\n------------\r\n\r\nFirst of all, you need to create a GATTRequester, passing the address\r\nof the device to connect to. Then, you can read a value defined by\r\neither by its handle or by its UUID. For example:\r\n\r\n    from gattlib import GATTRequester\r\n\r\n    req = GATTRequester(\"00:11:22:33:44:55\")\r\n    name = req.read_by_uuid(\"00002a00-0000-1000-8000-00805f9b34fb\")[0]\r\n    steps = req.read_by_handle(0x15)[0]\r\n\r\nReading data asynchronously\r\n--------------------------\r\n\r\nThe process is almost the same: you need to create a GATTRequester\r\npassing the address of the device to connect to. Then, create a\r\nGATTResponse object, on which receive the response from your\r\ndevice. This object will be passed to the `async` method used.\r\n\r\n**NOTE**: It is important to maintain the Python process alive, or the\r\nresponse will never arrive. You can `wait` on that response object, or you\r\ncan do other things meanwhile.\r\n\r\nThe following is an example of response waiting:\r\n\r\n    from gattlib import GATTRequester, GATTResponse\r\n\r\n    req = GATTRequester(\"00:11:22:33:44:55\")\r\n    response = GATTResponse()\r\n\r\n    req.read_by_handle_async(0x15, response)\r\n    while not response.received():\r\n        time.sleep(0.1)\r\n\r\n    steps = response.received()[0]\r\n\r\nAnd then, an example that inherits from GATTResponse to be notified\r\nwhen the response arrives:\r\n\r\n    from gattlib import GATTRequester, GATTResponse\r\n\r\n    class NotifyYourName(GATTResponse):\r\n        def on_response(self, name):\r\n            print(\"your name is: {}\".format(name))\r\n\r\n    response = NotifyYourName()\r\n    req = GATTRequester(\"00:11:22:33:44:55\")\r\n    req.read_by_handle_async(0x15, response)\r\n\r\n    while True:\r\n        # here, do other interesting things\r\n        sleep(1)\r\n\r\nWriting data\r\n------------\r\n\r\nThe process to write data is the same as for read. Create a\r\nGATTRequest object, and use the method `write_by_handle` to send the\r\ndata. As a note, data must be a string, but you can convert it from\r\n`bytearray` or something similar. See the following example:\r\n\r\n    from gattlib import GATTRequester\r\n\r\n    req = GATTRequester(\"00:11:22:33:44:55\")\r\n    req.write_by_handle(0x10, str(bytearray([14, 4, 56])))\r\n\r\nReceiving notifications\r\n-----------------------\r\n\r\nTo receive notifications from remote device, you need to overwrite the\r\n`on_notification` method of `GATTRequester`. This method is called\r\neach time a notification arrives, and has two params: the handle where\r\nthe notification was produced, and a string with the data that came in\r\nthe notification event. The following is a brief example:\r\n\r\n    from gattlib import GATTRequester\r\n\r\n    class Requester(GATTRequester):\r\n        def on_notification(self, handle, data):\r\n            print(\"- notification on handle: {}\\n\".format(handle))\r\n\r\nYou can receive indications as well. Just overwrite the method\r\n`on_indication` of `GATTRequester`.\r\n\r\nDisclaimer\r\n==========\r\n\r\nThis software may harm your device. Use it at your own risk.\r\n\r\n    THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\r\n    APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\r\n    HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT\r\n    WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\r\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n    A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\r\n    PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\r\n    DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR\r\n    CORRECTION.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewelse%2Fpygattlib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatthewelse%2Fpygattlib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewelse%2Fpygattlib/lists"}