Giter Site home page Giter Site logo

gatt-python's Introduction

Bluetooth GATT SDK for Python

The Bluetooth GATT SDK for Python helps you implementing and communicating with any Bluetooth Low Energy device that has a GATT profile. As of now it supports:

  • Discovering nearby Bluetooth Low Energy devices
  • Connecting and disconnecting devices
  • Implementing your custom GATT profile
  • Accessing all GATT services
  • Accessing all GATT characteristics
  • Reading characteristic values
  • Writing characteristic values
  • Subscribing for characteristic value change notifications

Currently Linux is the only platform supported by this library. Unlike other libraries this GATT SDK is based directly on the mature and stable D-Bus API of BlueZ to interact with Bluetooth devices. In the future we would like to make this library platform-independent by integrating with more Bluetooth APIs of other operating systems such as MacOS and Windows.

Prerequisites

The GATT SDK requires Python 3.4+. Currently Linux is the only supported operating system and therefor it needs a recent installation of BlueZ. It is tested to work fine with BlueZ 5.44, any release >= 5.38 should however work, too.

Installation

These instructions assume a Debian-based Linux.

On Linux the BlueZ library is necessary to access your built-in Bluetooth controller or Bluetooth USB dongle. Some Linux distributions provide a more up-to-date BlueZ package, some other distributions only install older versions that don't implement all Bluetooth features needed for this SDK. In those cases you want to either update BlueZ or build it from sources.

Updating/installing BlueZ via apt-get

  1. bluetoothd --version Obtains the version of the pre-installed BlueZ. bluetoothd daemon must run at startup to expose the Bluetooth API via D-Bus.
  2. sudo apt-get install --no-install-recommends bluetooth Installs BlueZ
  3. If the installed version is too old, proceed with next step: Installing BlueZ from sources

Installing BlueZ from sources

The bluetoothd daemon provides BlueZ's D-Bus interfaces that is accessed by the GATT SDK to communicate with Bluetooth devices. The following commands download BlueZ 5.44 sources, built them and replace any pre-installed bluetoothd daemon. It's not suggested to remove any pre-installed BlueZ package as its deinstallation might remove necessary Bluetooth drivers as well.

  1. sudo systemctl stop bluetooth
  2. sudo apt-get update
  3. sudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev libdbus-glib-1-dev unzip
  4. cd
  5. mkdir bluez
  6. cd bluez
  7. wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.44.tar.xz
  8. tar xf bluez-5.44.tar.xz
  9. cd bluez-5.44
  10. ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-library
  11. make
  12. sudo make install
  13. sudo ln -svf /usr/libexec/bluetooth/bluetoothd /usr/sbin/
  14. sudo install -v -dm755 /etc/bluetooth
  15. sudo install -v -m644 src/main.conf /etc/bluetooth/main.conf
  16. sudo systemctl daemon-reload
  17. sudo systemctl start bluetooth
  18. bluetoothd --version # should now print 5.44

Please note that some distributions might use a different directory for system deamons, apply step 13 only as needed.

Enabling your Bluetooth adapter

  1. echo "power on" | sudo bluetoothctl Enables your built-in Bluetooth adapter or external Bluetooth USB dongle

Using BlueZ commandline tools

BlueZ also provides an interactive commandline tool to interact with Bluetooth devices. You know that your BlueZ installation is working fine if it discovers any Bluetooth devices nearby.

sudo bluetoothctl Starts an interactive mode to talk to BlueZ

  • power on Enables the Bluetooth adapter
  • scan on Start Bluetooth device scanning and lists all found devices with MAC addresses
  • connect AA:BB:CC:DD:EE:FF Connects to a Bluetooth device with specified MAC address
  • exit Quits the interactive mode

Installing GATT SDK for Python

To install this GATT module and the Python3 D-Bus dependency globally, run:

sudo pip3 install gatt
sudo apt-get install python3-dbus

Running the GATT control script

To test if your setup is working, run the gattctl tool that is part of this SDK. Note that it must be run as root because on Linux, Bluetooth discovery by default is a restricted operation.

sudo gattctl --discover
sudo gattctl --connect AA:BB:CC:DD:EE:FF # Replace the MAC address with your Bluetooth device's MAC address
sudo gattctl --help # To list all available commands

SDK Usage

This SDK requires you to create subclasses of gatt.DeviceManager and gatt.Device. The other two classes gatt.Service and gatt.Characteristic are not supposed to be subclassed.

gatt.DeviceManager manages all known Bluetooth devices and provides a device discovery to discover nearby Bluetooth Low Energy devices. You want to subclass this manager to access Bluetooth devices as they are discovered as well as to restrict the set of devices to those that you actually want to support by your manager implementation. By default gatt.DeviceManager discovers and returns all Bluetooth devices but you can restrict that by overriding gatt.DeviceManager.make_device().

gatt.Device is the base class for your Bluetooth device. You will need to subclass it to implement the Bluetooth GATT profile of your choice. Override gatt.Device.services_resolved() to interact with the GATT profile, i.e. start reading from and writing to characteristics or subscribe to characteristic value change notifications.

Discovering nearby Bluetooth Low Energy devices

The SDK entry point is the DeviceManager class. Check the following example to dicover any Bluetooth Low Energy device nearby.

import gatt

class AnyDeviceManager(gatt.DeviceManager):
    def device_discovered(self, device):
        print("Discovered [%s] %s" % (device.mac_address, device.alias()))

manager = AnyDeviceManager(adapter_name='hci0')
manager.start_discovery()
manager.run()

Please note that communication with your Bluetooth adapter happens over BlueZ's D-Bus API, hence an event loop needs to be run in order to receive all Bluetooth related events. You can start and stop the event loop via run() and stop() calls to your DeviceManager instance.

Connecting to a Bluetooth Low Energy device and printing all its information

Once gatt.DeviceManager has discovered a Bluetooth device you can use the gatt.Device instance that you retrieved from gatt.DeviceManager.device_discovered() to connect to it. Alternatively you can create a new instance of gatt.Device using the name of your Bluetooth adapter (typically hci0) and the device's MAC address.

The following implementation of gatt.Device connects to any Bluetooth device and prints all relevant events:

import gatt

manager = gatt.DeviceManager(adapter_name='hci0')

class AnyDevice(gatt.Device):
    def connect_succeeded(self):
        super().connect_succeeded()
        print("[%s] Connected" % (self.mac_address))

    def connect_failed(self, error):
        super().connect_failed(error)
        print("[%s] Connection failed: %s" % (self.mac_address, str(error)))

    def disconnect_succeeded(self):
        super().disconnect_succeeded()
        print("[%s] Disconnected" % (self.mac_address))

    def services_resolved(self):
        super().services_resolved()

        print("[%s] Resolved services" % (self.mac_address))
        for service in self.services:
            print("[%s]  Service [%s]" % (self.mac_address, service.uuid))
            for characteristic in service.characteristics:
                print("[%s]    Characteristic [%s]" % (self.mac_address, characteristic.uuid))


device = AnyDevice(mac_address='AA:BB:CC:DD:EE:FF', manager=manager)
device.connect()

manager.run()

As with device discovery, remember to start the Bluetooth event loop with gatt.DeviceManager.run().

Reading and writing characteristic values

As soon as gatt.Device.services_resolved() has been called by the SDK, you can access all GATT services and characteristics. Services are stored in the services attribute of gatt.Device and each gatt.Service instance has a characteristics attribute.

To read a characteristic value first get the characteristic and then call read_value(). gatt.Device.characteristic_value_updated() will be called when the value has been retrieved.

The following example reads the device's firmware version after all services and characteristics have been resolved:

import gatt

manager = gatt.DeviceManager(adapter_name='hci0')

class AnyDevice(gatt.Device):
    def services_resolved(self):
        super().services_resolved()

        device_information_service = next(
            s for s in self.services
            if s.uuid == '0000180a-0000-1000-8000-00805f9b34fb')

        firmware_version_characteristic = next(
            c for c in device_information_service.characteristics
            if c.uuid == '00002a26-0000-1000-8000-00805f9b34fb')

        firmware_version_characteristic.read_value()

    def characteristic_value_updated(self, characteristic, value):
        print("Firmware version:", value.decode("utf-8"))


device = AnyDevice(mac_address='AA:BB:CC:DD:EE:FF', manager=manager)
device.connect()

manager.run()

To write a characteristic value simply call write_value(value) on the characteristic with value being an array of bytes. Then characteristic_write_value_succeeded() or characteristic_write_value_failed(error) will be called on your gatt.Device instance.

Subscribing for characteristic value changes

To subscribe for characteristic value change notifications call enable_notifications() on the characteristic. Then, on your gatt.Device instance, characteristic_enable_notification_succeeded() or characteristic_enable_notification_failed() will be called. Every time the Bluetooth device sends a new value, characteristic_value_updated() will be called.

Support

Please open an issue for this repository.

Contributing

Contributions are welcome via pull requests. Please open an issue first in case you want to discus your possible improvements to this SDK.

License

The GATT SDK for Python is available under the MIT License.

gatt-python's People

Contributors

ajtag avatar cal-id avatar commento avatar grunskis avatar jlusiardi avatar kelada avatar larsblumberg avatar papapumpkins avatar yukoba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gatt-python's Issues

remove_all_devices raises a DBusException

A DBusException can be propagated out of remove_all_devices. I would expect that the user would never see DBus exceptions as are platform specific...

self._manager.remove_all_devices()
File "/usr/local/lib/python3.6/dist-packages/gatt/gatt_linux.py", line 221, in remove_all_devices
self._adapter.RemoveDevice(path)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 70, in call
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in call
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "RemoveDevice" with signature "s" on interface "org.bluez.Adapter1" doesn't exist

Unexpected keyword argument error when enabling notifications

I am getting the following error in characteristic_enable_notifications_succeeded():

Traceback (most recent call last): File "/usr/lib/python3/dist-packages/dbus/connection.py", line 604, in msg_reply_handler reply_handler(*message.get_args_list(**get_args_opts)) File "/usr/local/lib/python3.5/dist-packages/gatt/gatt_linux.py", line 618, in _enable_notifications_succeeded self.service.device.characteristic_enable_notifications_succeeded(characteristic=self) TypeError: characteristic_enable_notifications_succeeded() got an unexpected keyword argument 'characteristic'

I am not sure what is causing this issue.

Loss of synchronisation

Devices get out of sync with their bluez counterparts. For instance I just had it so that is_services_resolved() would immediately return true and the services_resolved event was never triggered on the device. After a 'sudo /etc/init.d/bluetooth restart', the problem went away. The Adafruit Bluefruit LE library offers a clear_cache function to help with this same issue.

To expand a bit, is_services_resolved() returned true but the services list of the device was empty.

service: "Device Information" will be created automatically with the PnP_ID characteristic Bluez version above 5.50

Hey,

I' currently working on a project where I use the GATT Server and the GATT advertiser.

Problem:

  • If Bluez is compiled from source following this post link](https://scribles.net/updating-bluez-on-raspberry-pi-from-5-43-to-5-50/). (Please replace the Bluez version with the actual one Bluez5.5 )
  • Then if the Python script is used with bluez version 5.50 or 5.54 in order to create the Gatt Server then the service: "Device Information" will be created automatically with the PnP_ID characteristic.
  • If in the Gatt Server python script the service: "Device Information" is also defined, then it will result in having 2 "Device Information" Services which are not combined. (Checkable via nRF app)
  • In my case for example, my scripts checks if "Device Information" is available and want to check the software version string characteristic. But as it already sees the "Device Information" service with only having the PnP_ID characteristic, my script fails.
    I have no idea for the moment how to prevent Bluez version above 5.50 to create "Device Information" service with the PnP_ID characteristic.

Short Term solution:

  • Do not upgrade Bluez higher as 5.50 if the full control over the Service: Device Information wants be maintained.

Tested on/with:

  • Raspberry pi 1 (Gatt Server)
    • Bluetooth dongle 4.1
    • Raspberry Pi OS Lite 02.12.2020
    • Bluez 5.44 ==> Service: Device Information automatically created with PnP_ID characteristic
    • Bluez 5.55 ==> Service: Device Information automatically created with PnP_ID characteristic
    • Bluez 5.50 ==> No Service Device Information automatically created
  • Raspberry pi zero W (Gatt Server)
    • Bluetooth on board 4.1
    • Raspberry Pi OS Lite 02.12.2020
    • Bluez 5.44 ==> Service: Device Information automatically created with PnP_ID characteristic
    • Bluez 5.55 ==> Service: Device Information automatically created with PnP_ID characteristic
    • Bluez 5.50 ==> No Service Device Information automatically created
  • Android: (BLE client)
    • Version 6.0
    • Version 8.0
    • Version 10.0
    • Checked with nRF app

Request:

  • Has someone already a longterm solution for this problem. Should I change something during the compilation ? or can I control via the python GATT server script and DBUS that Bluez shouldn't create the "Device Information" service on it's own.

HID over GATT

I stumbled upon this library and I was able to connect to my Bluetooth LE device. However, since it uses HID over GATT I could currently not go further.

Currently I'm trying to connect my Bluetooth LE Remote to a Raspberrypi only with partial success so far.

Did you intend to, at some point implement the HID over GATT profile. Currently it looks like I'll have to implement the protocol myself and this could be part of gatt-python or by using it as a dependency.

You may let me know if this is at all somehow in the scope of where gatt-python is heading.
You may, of course, close this issue, if this is not in the scope or seems to be too off-topic.

mac addresses appear to be case sensitive (trivial)

After cut&pasting my BLE device address from gattool where it's all upper case, I got

[A4:C1:38:CE:0D:F5] Connection failed: Device does not exist, check adapter name and MAC address.

After running ./gattctl.py --discover I noticed the output was all lower case, so on a hunch, I downcased it and got

[a4:c1:38:ce:0d:f5] Connected

(yay!) I just suggest calling it out in the example, or throwing in a .lower() and avoiding the issue, since other (linux, at least) tools are case-insensitive here.

GATT Server

Is it possible to use this library to create a GATT server? I am creating a Raspberry Pi smart device and I need to be able to connect to it from a mobile device (not the other way around). Any suggestions on how to do that? Thanks!

Passive scan feature

Hi!

I would need a passive scan function to get the RSSI values from advertisement data at a relative high rate (like hcitool lescan --passive). The discover function is way too slow for this.

Is this even supported by the dbus API? I don't know where to start.

Best regards

Property `Alias` on `Device1` is sometimes not available

  File "/srv/senic_hub/venv/lib/python3.5/site-packages/gatt/gatt_linux.py", lin
e 354, in alias
    return self._properties.Get('org.bluez.Device1', 'Alias')
  File "/usr/lib/python3.5/site-packages/dbus/proxies.py", line 70, in __call__
    return self._proxy_method(*args, **keywords)
  File "/usr/lib/python3.5/site-packages/dbus/proxies.py", line 145, in __call__

    **keywords)
  File "/usr/lib/python3.5/site-packages/dbus/connection.py", line 651, in call_
blocking
    message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: Method
"Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't
 exist

We can catch this exception and return None as the device's alias.

BlueZ work SDK not

hi installation from package so far so good bluez5.9 works fine (I hope), gatt and dbus for python seems ok, but sudo gattctl --discover crash:

pi@raspberrypi:~/bluez-5.9 $ sudo gattctl --discover
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/gatt/gatt_linux.py", line 138, in start_discovery
self._adapter.SetDiscoveryFilter(discovery_filter)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 70, in call
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in call
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "SetDiscoveryFilter" with signature "a{ss}" on interface "org.bluez.Adapter1" doesn't exist

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/bin/gattctl", line 11, in
sys.exit(main())
File "/usr/local/lib/python3.5/dist-packages/gattctl.py", line 116, in main
device_manager.start_discovery()
File "/usr/local/lib/python3.5/dist-packages/gatt/gatt_linux.py", line 149, in start_discovery
raise _error_from_dbus_error(e)
gatt.errors.Failed: Method "SetDiscoveryFilter" with signature "a{ss}" on interface "org.bluez.Adapter1" doesn't exist

Where could be a problem, what am I doing wrong?

[SOLVED] Module 'dbus' not found

Hi.
I keep getting an error about 'dbus' module not being found:

Module 'dbus' not found
Please run: sudo apt-get install python3-dbus
See also: https://github.com/getsenic/gatt-python#installing-gatt-sdk-for-python

though I had successfully installed the module before:

python3-dbus is already the newest version (1.2.6-1)

Did anyone experience similar problem?

Writing to characteristic values from outside the event loop

I'm not sure how to make use of the event loop properly:
I would like to use the GATT SDK inside a flask server. When a http request is sent to the server I would like to write a value to a characteristic (by handle). But how can I access the DeviceManager or even start / stop it once it is running forever?

Feature Request: Ability to be able to disconnect already connected devices

Feature Request: Ability to be able to disconnect already connected devices

For example when something goes wrong and you don't get to disconnect nicely from a device, the next time you try to discover that device it is no longer available so you cannot connect to it again.

The ability to get a list of currently connected devices, then check if they offer the service you care about then disconnect them would be great. Similar to in the Adafruit BlueFruitLE libraries disconnect_devices([SERVICE_UUID]).

Otherwise, a great library, works well...

how to transfer 4MB file from my rpi3 to other ble devices through descriptors

       I have followed all the instructions in this GATT SDK. i am able to write the characteristic and read the characteristic. could you please any one help me to transfer  and receive 4MB data from rpi3 to other BLE's, through descriptor.
        
        i have one problem in reading and writing the characteristic,which means i need to maintain two python file one for writing the characters and another one for reading the character.please tell me anyone how to merge this two files
        in that first i need to call "write" function and second i need call "read" function

And if possible please share GATT SDK document

gatt-python - "random" LE address type?

Hello,

I have a problem connecting to BLE device using gatt-python:

$ sudo gattctl --connect E5:D4:39:0E:87:21
Connecting...
[E5:D4:39:0E:87:21] Connection failed: Device does not exist, check adapter name and MAC address.
Terminate with Ctrl+C

Simultaneously I can connect (and operate device with gatt commands) using regular "gatttool":

$ sudo gatttool -b E5:D4:39:0E:87:21 -t random --primary
attr handle = 0x0001, end grp handle = 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle = 0x0008, end grp handle = 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle = 0x0009, end grp handle = 0xffff uuid: 6e400001-b5a3-f393-e0a9-e50e24dcca9e

However - it is possible only in "random" LE address type ("-t random" option)

When I try to use gatttool in default mode ("public" LE address type):
$ sudo gatttool -b E5:D4:39:0E:87:21 --primary

I receive:
connect error: Connection refused (111)

Maybe it is the same problem with gatt-python???
Is there a possibility to switch to random LE address type in gatt-python?

Regards,
ML

PS.
Bluez 5.43
python3-dbus 1.2.4-1
gatt-0.2.6

Disconnecting right after connecting

Hi, i am trying to connect to a GATT server on my Linkit 7697 board from my Raspberry Pi 3 Model B. I tried out the 'Discovering nearby Bluetooth Low Energy devices' example and my device did appear. However when i tried running other examples it would connect and disconnect immediately. How do i solve this?

descriptor_read_value_failed Callback

If a descriptor value fails to be read, the Descriptor method read_value will call:
self.service.device.descriptor_read_value_failed(self, error=error).

This causes an error because the Descriptor class has no 'service' property.
The line should be corrected to:
self.characteristic.service.device.descriptor_read_value_failed(self, error=error).

This Class exists in gatt_linux.py. The offending code is on line 541 of this file.

DBus Socket not found

I'm running this in a conda environment and getting this problem:

dbus.exceptions.DBusException: org.freedesktop.DBus.Error.FileNotFound: Failed to connect to socket /home/andi/anaconda3/envs/py37/var/run/dbus/system_bus_socket: No such file or directory

Obviously it shouldn't be looking for the dbus socket in that path right?

Occasional large delays when connecting to multiple peripherals

Using Bluetoothctl I can connect to 3 peripherals in parallel without additional delays. So one connection takes 3-6 seconds (we have some really constrained connection parameters on our peripherals) and for 3 peripherals it still takes 3-6 seconds per connection.

With gatt-python we're seeing extreme large delays but not always... . For instance on an average of 10 connect/disconnect cycles with 3 peripherals: Average total connection duration 135.988185 seconds with a min/max value of 8/263.836915 seconds. So sometimes it only takes 8 seconds but it can also take 263 seconds. Very inconsistent and hard to debug.

I presume it's rather D-Bus related or perhaps gatt-python performs some additional load on D-bus?

I'm struggling really hard to debug this because when waiting for 200+ seconds on an connect_xxx callback there are no entries in bluetoothd and dbus-monitor logs. So the system hangs and there is not a single indication of why this is happening.

Characteristic write value time highly variable across machines

I'm communicating with some Sphero robots for a project with this library, and I am finding that the time it takes for a characteristic write_value call to get to the write_value succeeded is ~.01 seconds on one Linux machine, and ~.1 on another.

This is at the same distance to the robot. Anything that might explain the variability? Not sure where to start looking.

connect is blocking other device updates

I have 2 BLE sensors both transmitting continuously. I then cut power to one of the sensors. On disconnect, I try to try re-establishing connection to the BLE device by calling connect. This blocks all the updates from the other sensor until the connect fails. Is this the expected behaviour?

rpi3 can not run discovery.py

Hi all, @larsblumberg
when i run discovery.py which is in example directory on my rpi3, it has same error shown as below,
my python version is 3.4 and blueZ is 5.23
who can tell me how to solve this? thanks!

pi@raspberrypi:~/workspace/gatt-python/examples $ ./discovery1.py
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/gatt/gatt_linux.py", line 137, in start_discovery
self._adapter.SetDiscoveryFilter(discovery_filter)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 70, in call
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in call
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "SetDiscoveryFilter" with signature "a{ss}" on interface "org.bluez.Adapter1" doesn't exist

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "./discovery1.py", line 10, in
manager.start_discovery()
File "/usr/local/lib/python3.4/dist-packages/gatt/gatt_linux.py", line 148, in start_discovery
raise _error_from_dbus_error(e)
gatt.errors.Failed: Method "SetDiscoveryFilter" with signature "a{ss}" on interface "org.bluez.Adapter1" doesn't exist

discovery1

Report all data from advertisement during discovery

From the examples it seems that only the device name and the MAC address are reported during a discovery. This was ok for classic bluetooth. But BLE can also deliver UUIDs during the undirected advertisement which is very useful for device discovery.

E.g. the Lego WeDo-2.0 hub is otherwise impossible to identify as the user is allowed to change the device name and the OID is from Texas Instruments. Thus the UUID from the undirected advertisement is needed to detect the device.

read characteristic value

Hello,

I am running this code on my peripheral that sends battery level periodically. But I am not able to get it.
A simple read_val also does not work. Please help.

Ubuntu 18.04

import gatt
from argparse import ArgumentParser

class AnyDevice(gatt.Device):
    def services_resolved(self):
        super().services_resolved()

        battery_information_service = next(
            s for s in self.services
            if s.uuid == '00001801-0000-1000-8000-00805f9b34fb')

        for c in battery_information_service.characteristics:
            c.enable_notifications(True)

        print("Reading Battery")

    def characteristic_value_updated(self, characteristic, value):
        print("Battery level:", value.decode("utf-8"))


arg_parser = ArgumentParser(description="GATT Read Firmware Version Demo")
arg_parser.add_argument('mac_address', help="MAC address of device to connect")
args = arg_parser.parse_args()

manager = gatt.DeviceManager(adapter_name='hci0')

device = AnyDevice(manager=manager, mac_address=args.mac_address)
device.connect()

manager.run()

Read the values in hexadecimal and not in ASCII

Hi!

When I try to read a value between 32 DEC and 126 DEC , the readed value shows in ASCII.
But when I read a value between 00 DEC and 127 DEC , or between 127 DEC and 255 DEC, the readed value shows in Hexadecimal.

I want to read all the values in hexadecimal.

Configure Raspberry PI3 in BLE slave mode ?

Hello,

I would like to configure a raspberry pi 3 in slave mode BLE to simulate a sensor, but it seems not possible do to it with gatt-python. Do you know how to do it ?

Thank you in advance.
Michel

Bluetooth related errors when testing with nrf52 dev board

While testing the nrf52 dev board I found it to be inconsistent. The following logs are the most common errors which all appear to point back to the gatt-python/gatt/gatt_linux.py file.

The following exceptions are found the the nuimo_app.log file:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.5/site-packages/gatt/gatt_linux.py", line 274, in _connect
    self._object.Connect()
  File "/usr/lib/python3.5/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib/python3.5/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: Method "Connect" with signature "" on interface "org.bluez.Device1" doesn't exist

and

  File "/usr/lib/python3.5/site-packages/nuimo/nuimo.py", line 135, in connect_failed
    self.listener.connect_failed(error)
  File "/home/root/senic-hub/senic_hub/nuimo_app/__init__.py", line 38, in connect_failed
    self.controller.connect()
  File "/usr/lib/python3.5/site-packages/nuimo/nuimo.py", line 130, in connect
    super().connect()
  File "/usr/lib/python3.5/site-packages/gatt/gatt_linux.py", line 269, in connect
    self._connect()
  File "/usr/lib/python3.5/site-packages/gatt/gatt_linux.py", line 279, in _connect
    self.connect_failed(errors.Failed("Device does not exist, check adapter name and MAC address."))

The following exceptions are found the the senic_hub.log file:

2017-11-13 14:18:00,279 ERROR [waitress] Exception when serving /-/confnuimos
Traceback (most recent call last):
  File "/usr/lib/python3.5/site-packages/waitress/channel.py", line 338, in service
    task.service()
  File "/usr/lib/python3.5/site-packages/waitress/task.py", line 169, in service
    self.execute()
  File "/usr/lib/python3.5/site-packages/waitress/task.py", line 399, in execute
    app_iter = self.channel.server.application(env, start_response)
  File "/usr/lib/python3.5/site-packages/raven/middleware.py", line 98, in __call__
    iterable = self.application(environ, start_response)
  File "/usr/lib/python3.5/site-packages/pyramid/router.py", line 236, in __call__
    response = self.invoke_subrequest(request, use_tweens=True)
  File "/usr/lib/python3.5/site-packages/pyramid/router.py", line 211, in invoke_subrequest
    response = handle_request(request)
  File "/usr/lib/python3.5/site-packages/pyramid/tweens.py", line 51, in excview_tween
    request_iface=request_iface.combined
  File "/usr/lib/python3.5/site-packages/pyramid/view.py", line 547, in _call_view
    response = view_callable(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/viewderivers.py", line 413, in viewresult_to_response
    result = view(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/tweens.py", line 22, in excview_tween
    response = handler(request)
  File "/usr/lib/python3.5/site-packages/pyramid/router.py", line 158, in handle_request
    view_name
  File "/usr/lib/python3.5/site-packages/pyramid/view.py", line 547, in _call_view
    response = view_callable(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/config/views.py", line 182, in __call__
    return view(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/viewderivers.py", line 393, in attr_view
    return view(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/viewderivers.py", line 371, in predicate_wrapper
    return view(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/viewderivers.py", line 442, in rendered_view
    result = view(context, request)
  File "/usr/lib/python3.5/site-packages/pyramid/viewderivers.py", line 147, in _requestonly_view
    response = view(request)
  File "/usr/lib/python3.5/site-packages/cornice/service.py", line 493, in wrapper
    response = view_(request)
  File "/home/root/senic-hub/senic_hub/backend/views/nuimos.py", line 102, in get_configured_nuimos
    config['nuimos'][mac_address]['is_connected'] = controller.is_connected()
  File "/usr/lib/python3.5/site-packages/gatt/gatt_linux.py", line 342, in is_connected
    return self._properties.Get('org.bluez.Device1', 'Connected') == 1
  File "/usr/lib/python3.5/site-packages/dbus/proxies.py", line 70, in __call__
    return self._proxy_method(*args, **keywords)
  File "/usr/lib/python3.5/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib/python3.5/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't exist

Cannot get characteristics of battery service

I'm struggling with reading the battery value of a peripheral.
The peripheral is based on a Nordic nrf52 and implements the battery service 0x180F and a read characteristic.

After connecting to the device I can find the battery service, but it does not contain any characteristics, although I can confirm that they exist with the 'nrfConnect' app.

Has anyone succeeded in reading the battery value of a peripheral or in discovering its battery characteristics?

Activate Notifications Client Characteristic Configuration Descriptor

Hello!

The situation is the following:
I'm using the gatt library for communicate between a raspberry Pi 3 (python, Client) and the bluenrg module for the nucleo F103-RB(Server, C).

The library works correctly both to read and to write. But I can't activate the notifications. To receive notifications, it must activate the Client Characteristic Configuration Descriptor ( UUID = 0x2902 ) through the handle of this notification, writing a 0x0200.

When I readed the characteristics of the servers, I didn't see this characteristic.

My code is:

import gatt
import time

manager = gatt.DeviceManager(adapter_name='hci0')

class AnyDevice(gatt.Device):
def services_resolved(self):
super(AnyDevice,self).services_resolved()

    serv = next(
        s for s in self.services
        if s.uuid == 'd973f2e7-b19e-11e2-9e96-0800200c9a66') 

    char = next(
        c for c in serv.characteristics
        if c.uuid == 'd973f2e8-b19e-11e2-9e96-0800200c9a66')
    
    char.enable_notifications()
    char.write_value(b'\x22')
    #char.read_value()
    

def characteristic_value_updated(self, characteristic, value):
    print('updated value: ' + str(value))
    self.disconnect()
    self.manager.stop()

def characteristic_enable_notification_succeeded(self, characteristic):
    print("Notification Enabled")

def characteristic_enable_notification_failed(self, characteristic, error):
    print("Error")

device = AnyDevice(mac_address='02:80:e1:01:01:aa', manager=manager)
device.connect()

manager.run()


¿Can I find the handle of all the characteristics?
¿ How Could I write to the 0x2902( CCCD) ?

Thanks you so much

Jordi

Cannot write_value twice through BlueZ

Hi, I'm using BlueZ 5.50,
When I send value through BlueZ, it's work properly the first time but when I call the function a second time the dbus send me back an error (InProgress):
write value failed
write value fail for characteristic 6e400002-b5a3-f393-e0a9-e50e24dcca9e , error, In Progress
write value succeeded
write value succeeded for characteristic 6e400002-b5a3-f393-e0a9-e50e24dcca9e

my code :
characteristic_tx.write_value(str)
time.sleep(10)
characteristic_tx.write_value(str)

Do I need to send something to clear BlueZ flag ?

I'm not used to Python, how can I generate interruption in GObject.MainLoop() to send data through BlueZ ?

Charactristic notify callback not removed on device disconnect

It seems that the characteristic notify callback that is registered with the underlying layer is not removed when a device disconnects. When you reconnect to that device and register a notify callback it is called twice for each time data is received. Every time you disconnect/reconnect and register the callback you get one more call of the callback each time. Note that a new derived gatt.Device is instantiated on each connect.

In my disconnect code I call .enable_notifications(False) on the particular characteristic in question. Seems to work correctly if the central is causing the disconnect. However, if the peripheral device is remotely disconnected (e.g. powered off), then device.services is no longer valid to obtain the characteristic to call enable_notifications on.

I would assume it is the responsibility of the destructing code to clean up any callbacks registered?

Any ideas how to work around this?

Insufficient Authorization

Hi all,

on my Raspberry Pi 4, I'm trying to write some characteristics using this gatt module.
However, I run into the following issue:

> ACL Data RX: Handle 64 flags 0x02 dlen 9                                               #36 [hci0] 17.312990
      ATT: Error Response (0x01) len 4
        Write Request (0x12)
        Handle: 0x0020
        Error: Insufficient Authorization (0x08)

The python code looks like this:

import gatt

manager = gatt.DeviceManager(adapter_name='hci0')

class AnyDevice(gatt.Device):
    def services_resolved(self):
        super().services_resolved()

        device_information_service = next(
            s for s in self.services
            if s.uuid == '00001234-0000-1000-8000-001234567890')

        firmware_version_characteristic = next(
            c for c in device_information_service.characteristics
            if c.uuid == '00001235-0000-1000-8000-001234567890')

        firmware_version_characteristic.write_value(b'start')

    def characteristic_write_value_succeeded(self, characteristic):
        """
        Called when a characteristic value write command succeeded.
        """
        # To be implemented by subclass
        print("worked")

    def characteristic_write_value_failed(self, characteristic, error):
        """
        Called when a characteristic value write command failed.
        """
        # To be implemented by subclass
        print("failed")


device = AnyDevice(mac_address='00:21:7E:24:A7:F1', manager=manager)
device.connect()

manager.run()

On my computer, this works without any issues. On the RPI, i get the autohrization error.

I read that you can set the permissions in the gatt, but couldn't find a proper function in the implementation.

Any ideas?

Thanks,
Soner

stop main loop

how to stop main loop, because there is blocking, and and I can't call stop function, this my code

import gatt

manager = gatt.DeviceManager(adapter_name='hci0')

class AnyDevice(gatt.Device):
def services_resolved(self):
super().services_resolved()

    device_proprietary_service = next(
        s for s in self.services
        if s.uuid == 'd0cbda9a-9a69-49ab-b4d1-a96d6fbd10c6')

    psp = next(
        c for c in device_proprietary_service.characteristics
        if c.uuid == 'd0cb6c99-9a69-49ab-b4d1-a96d6fbd10c6')

psp.write_value(bytearray(b'\x0a'))
tes="\x1D\x5A\x02"
best=tes.encode()
psp.write_value(best)
kay="\x1B\x5A\x00\x4C\x08\x11\x00\x43\x44\x3A\x42\x30\x3A\x32\x31\x3A\x32\x31\x3A\x34\x30\x3A\x42\x33"
best=kay.encode()
psp.write_value(best)

def characteristic_value_updated(self, characteristic, value):
    print(str(characteristic)+", value: "+value.decode("utf-8"))

def characteristic_write_value_succeeded(self, characteristic):
    print("Write successful.")

def characteristic_write_value_failed(self, characteristic, error):
    print("Write failed. "+str(error))

class Manager(gatt.DeviceManager):
def run(self):
print("Running Manager")
super().run()
def quit(self):
print("Stopping Manager")
super().stop()

manager = Manager(adapter_name = 'hci0')
device = AnyDevice(mac_address='CD:B0:21:21:40:B3', manager=manager)
device.connect()

manager.run()
time.sleep(2)
manager.quit()

Is this project still alive?

I'm trying to build a BLE device in python and I'm looking for a solution like this, but I don't see any recent update of the repo. Is the project still alive? Does it have some API documentation?

Unable to scan ble devices using service uuid

I have tried using the code below.

manager = ScanDevice(adapter_name='hci0',uuid='00001818-0000-1000-8000-00805f9b34fb')

But not able to discover getting an error as an invalid parameter.

SetDiscoveryFilter not working

Hello,

Thank you for developing the python Bluetooth LE library.
I'm trying to learn Bluetooth, and I am testing a dwm1001-dev device.

It uuid is 680c21d9-c946-4c1f-9c11-baa1c21329e7, I check for many times.

Here is my debugging code:

#!/usr/bin/env python3
import dbus
import gatt

class DeviceManager(gatt.DeviceManager):
    def device_discovered(self,device):
        print("Discovered [%s] %s" %
             (device.mac_address, device.alias()))

if __name__ == '__main__':
    manager = DeviceManager(adapter_name='hci0')
    list = manager._adapter.GetDiscoveryFilters()
    uuid = '680c21d9-c946-4c1f-9c11-baa1c21329e7'
    print(list)
    print(list[0])
    print(list[1])
    print(list[2])
    print(list[3])
    print(list[4])
    if False:
       manager.start_discovery([uuid])
    else:
        if False:
            manager._adapter.SetDiscoveryFilter({
                dbus.String("UUIDs"):[dbus.String(uuid)],
                dbus.String("Transport"):dbus.String("le")
                })
        else:
            manager._adapter.SetDiscoveryFilter({
                dbus.String("Transport"):dbus.String("le")
                })
        manager._adapter.StartDiscovery()
    manager.run()
    while True:
        pass

Output: when i set a filter with "UUIDs":['<uuid>'], it can't not discovery any devices.

device: Raspberry Pi B2
Bluetooth dongle: Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

version:

$ bluetoothd --version
5.48
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04 LTS
Release:        18.04
Codename:       bionic

wechat image_20180717111936

Difficulty working inside virtualenv

Just an FYI, I had difficulty setting this up in a virtualenv until I installed the following packages:

dbus-python==1.2.16
gatt==0.2.7
pkg-resources==0.0.0
ruamel.yaml==0.16.10
ruamel.yaml.clib==0.2.0
vext==0.7.3
vext.gi==0.7.0

After installing these packages, as well as reinstalling bluetoothd with the instructions provided in the README so that bluetoothd --version is5.44, gattctl --discover worked as expected.
I'm not sure whether the bluetoothd version matters, as I was previously on 5.48

Cannot connect to peripherals

Using the connect.py example.
With BlueZ 5.44 on a raspberry pi with Python 3.4.2 and a venv I get: "Connection failed: Device does not exist, check adapter name and MAC address"

With BlueZ 5.48 on my local PC with Python 3.5.2 but without a venv I get: "Connection failed: No such property 'ServicesResolved'"

On both systems I can execute the discovery.py example successfully and I can connect to the peripheral with gatttool.

Disconnecting example

For people unfamiliar with the dbus event loop. How are we supposed to cleanly shutdown after having written a value?

I added these in disconnect_succeeded:

device.disconnect()
manager.stop()

Should that suffice?

GObject - why dragging in such a huge dependency only for its mainloop?

Hello!

I wonder about why GObject is a dependency and apparently the only place where GObject is actually used, is gatt/gatt_linux.py:89: self._main_loop = GObject.MainLoop().
As PyGObject also requires GObject-introspection that's a huge I dependency and I wonder what's so special about its mainloop.

If I'm allowed to wish, I'd love to see this dependency gone, however - as I said - there might be good reasons I don't yet understand. Either way, I'd appreciate to understand what's so special about GObject's mainloop.

stop discovery and start to connect

I want to connect with ble device, but I only know UUID, therefore I try to discovery with UUID, discovery result managed to get ble device that I want. But when I want to connect, it can not be done because discovery continues to run, I am very confused how to stop discovery and connect with the ble device.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.