• Stars
    star
    521
  • Rank 84,389 (Top 2 %)
  • Language
    Python
  • License
    Other
  • Created over 10 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Python wrapper for gatttool (a deprecated tool from BlueZ) and the BGAPI for accessing Bluetooth LE Devices

pygatt - Python Module for Bluetooth LE Generic Attribute Profile (GATT).

This Module allows reading and writing to GATT descriptors on devices such as fitness trackers, sensors, and anything implementing standard GATT Descriptor behavior.

pygatt provides a Pythonic API by wrapping two different backends:

  • BlueZ (requires Linux), using the gatttool command-line utility.
  • Bluegiga's BGAPI, compatible with USB adapters like the BLED112.

Motivation

Despite the popularity of BLE, we have yet to find a good programming interface for it on desktop computers. Since most peripherals are designed to work with smartphones, this space is neglected. One interactive interface, BlueZ's gatttool, is functional but difficult to use programmatically. BlueZ itself obviously works, but the interface leaves something to be desired and only works in Linux.

Requirements

  • Python 2.7.5 or greater, or Python 3.5 or greater
    • Python 2.7.3's struct library has a bug that will break PyGATT - 2.7.5
      or greater is recommended.
  • BlueZ 5.18 or greater (with gatttool) - required for the gatttool backend only.
    • Tested on 5.18, 5.21, 5.35 and 5.43
  • GATTToolBackend requires Linux and sudo (i.e. not Windows compatible)

Installation

Install pygatt with pip from PyPI:

$ pip install pygatt

The BlueZ backend is not supported by default as it requires pexpect, which can only be installed in a UNIX-based environment. If you wish to use that backend, install the optional dependencies with:

$ pip install "pygatt[GATTTOOL]"

Install the latest development version of pygatt with pip:

$ pip install git+https://github.com/peplin/pygatt

Documentation

The documentation for pygatt consists of:

  • This README
  • The code in the samples directory
  • The Python docstrings in the code itself.

The BLEDevice and BLEBackend base classes are the primary interfaces for users of the library.

Known Issues

  • Performance has not been profiled, and there have been reports that both GATTTool and BGAPI backends struggled to handle high rate notifications (e.g. > 100Hz).
  • There is no way for the user to be notified if a device disconnects asynchronously (#306).
  • PIN-based authentication is not supported.
  • Duplicate characteristic names across different BLE service UUIDs are not supported.
  • Long characteristic reads and writes are only supported by the BGAPI backend.

Example Use

The primary API for users of this library is provided by pygatt.BLEBackend and pygatt.BLEDevice. After initializing an instance of the preferred backend (available implementations are found in pygatt.backends, use the BLEBackend.connect method to connect to a device and get an instance of BLEDevice.

import pygatt

# The BGAPI backend will attempt to auto-discover the serial device name of the
# attached BGAPI-compatible USB adapter.
adapter = pygatt.BGAPIBackend()

try:
    adapter.start()
    device = adapter.connect('01:23:45:67:89:ab')
    value = device.char_read("a1e8f5b1-696b-4e4c-87c6-69dfe0b0093b")
finally:
    adapter.stop()

Note that not all backends support connecting to more than 1 device at at time, so calling BLEBackend.connect again may terminate existing connections.

Here's the same example using the GATTTool backend. It's identical except for the initialization of the backend:

import pygatt

adapter = pygatt.GATTToolBackend()

try:
    adapter.start()
    device = adapter.connect('01:23:45:67:89:ab')
    value = device.char_read("a1e8f5b1-696b-4e4c-87c6-69dfe0b0093b")
finally:
    adapter.stop()

Notifications Example

This example uses the gatttool backend to connect to a device with a specific MAC address, subscribes for notifications on a characteristic, and prints the data returned in each notification.

import pygatt
from binascii import hexlify

adapter = pygatt.GATTToolBackend()

def handle_data(handle, value):
    """
    handle -- integer, characteristic read handle the data was received on
    value -- bytearray, the data returned in the notification
    """
    print("Received data: %s" % hexlify(value))

try:
    adapter.start()
    device = adapter.connect('01:23:45:67:89:ab')

    device.subscribe("a1e8f5b1-696b-4e4c-87c6-69dfe0b0093b",
                     callback=handle_data)

    # The subscription runs on a background thread. You must stop this main
    # thread from exiting, otherwise you will not receive any messages, and
    # the program will exit. Sleeping in a while loop like this is a simple
    # solution that won't eat up unnecessary CPU, but there are many other
    # ways to handle this in more complicated program. Multi-threaded
    # programming is outside the scope of this README.
    while True:
        time.sleep(10)
finally:
    adapter.stop()

Debugging

While debugging software using pygatt, it is often useful to see what's happening inside the library. You can enable debugging logging and have it printed to your terminal with this code:

import pygatt
import logging

logging.basicConfig()
logging.getLogger('pygatt').setLevel(logging.DEBUG)

Random Addressing

If you are having trouble connecting to a device, it may use random addressing. Try changing the connection setup code to:

device = adapter.connect('01:23:45:67:89:ab', address_type=pygatt.BLEAddressType.random)

Unexplained Timeouts

If you are experiencing unexplained timeouts with the gatttool backend, you may need to increase the supervisor timeouts:

echo 1000 > /sys/kernel/debug/bluetooth/hci0/supervision_timeout

Can't find BGAPI device in Windows

You may need to explicitly specify the COM port of your BGAPI-compatible device in windows, e.g.:

adapter = pygatt.BGAPIBackend(serial_port='COM9')

If you provide the COM port name, but still get an error such as WindowsError(2, 'The system cannot find the file specified.'), try changing the COM port of the device to a value under 10, e.g. COM9.

Authors

Releasing to PyPI

For the maintainers of the project, when you want to make a release:

  • Merge all of the changes into master.
  • Update the version in setup.py.
  • Update the CHANGELOG.mkd
  • Tag the commit and push to GitHub (will need to push to a separate branch of PR first since master is a protected branch).
  • Travis CI will take care of the rest - it will build and deploy tagged commits to PyPI automatically.

License

Copyright 2015 Stratos Inc. and Orion Labs

Apache License, Version 2.0 and MIT License. See LICENSE.

More Repositories

1

gpxviewer

Javascript GPX file viewer using Google Maps, updated for API v3
JavaScript
142
star
2

astral

A P2P content distribution network for live video
Python
25
star
3

arduino.mk

DEPRECATED FORK: Arduino Makefile with chipKIT support
Shell
11
star
4

redmine_create_wiki_page

Redmine plugin that adds a "New" button to each wiki page
HTML
8
star
5

head-pose-estimator

Slightly modified source from a paper by Gabriele Fanelli et. all
C++
8
star
6

vim-phabrowse

vim-fugitive extension for Phabricator
Vim Script
5
star
7

astral-web

Web Interface for Astral
JavaScript
4
star
8

threephase

Real-time electric power system strategy game (on Rails)
JavaScript
4
star
9

pflac

modifications to the official FLAC encoder (circa 2008) for parallel encoding
C++
3
star
10

trinity

RESTful neo4j wrapper in Python
Python
3
star
11

jtrie

A Java trie (prefix tree)
Java
3
star
12

asterisk-cookbook

DEPRECATED: Asterisk cookbook for Chef, with Google Voice support
Ruby
3
star
13

netflix-ratings-extractor

Fork of source from userscripts.org
JavaScript
3
star
14

orbiterjs

ProcessingJS Rocket Launch to Orbit Simulator
JavaScript
3
star
15

asterisk-google-voice-config

Minimal configuration for Asterisk 11 to use Google Voice for calls
3
star
16

spade

Experimental HTTP Server for Dynamic Content in C
C
2
star
17

ecomcat_to_openxc

Convet ECOMCat CAN message trace files to the OpenXC raw CAN format
Python
2
star
18

august23

August 23, 1966 - a University of MIchigan GROCS project from 2009
Java
2
star
19

wiremap-shapes

A few gemoetric shapes for a Wiremap, powered by Processing
Java
1
star
20

catman

Processing
1
star
21

hab-visualizer

JavaScript
1
star
22

pulse-oximeter

Processing
1
star
23

jsvim-tiddly

jsvim Plugin for TiddlyWiki
JavaScript
1
star
24

ati_remote

ATI Remote Wonder Linux Kernel Module (ati_remote)
C
1
star
25

hoppy

Hoptoad API in Python
Python
1
star
26

asana-burndown

Use the Asana API to calculate task counts and project burndown
Python
1
star
27

neb

Python library to access the Trinity API
Python
1
star
28

bueda-ruby

Lightweight Ruby wrapper for the Bueda API
Ruby
1
star
29

riddly

ActiveRecord models for an existing ccTiddly database
Ruby
1
star
30

peplin.github.com

SCSS
1
star
31

rdiosync

Rdio Filesystem Collection Sync
Python
1
star
32

git-presentation

showoff presentation on Git
1
star
33

scrapescrobbler

Submit songs to last.fm from old-fashioned radio stations
Ruby
1
star