question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Enhancement] - More useful example get_services.py

See original GitHub issue
  • bleak version: 0.7.1
  • Python version: 3.8
  • Operating System: Windows 10 - v1909
  • BlueZ version (bluetoothctl -v) in case of Linux: –

Description

@hbldh and the other contributors. Hi, Thank you so much for this amazing library !!! Very impressive that you made a platform agnostic GATT client.

I am still messing around and was trying the examples. I found the ‘get_services.py’ not useful enough as it just prints:

Services: <bleak.backends.service.BleakGATTServiceCollection object at 0x00000183F9F2D4C0>

I had to explore this object in debug mode as well as to dig a bit in the library to understand what this object has to offer. I wrote a script that explores each services, characteristics and descriptors and extracts the available information. I think it can be a good example for newcomers and wanted to contribute back.

Here’s my script:

"""
Services
----------------
An example showing how to fetch all services and print them.
Updated on 2019-03-25 by hbldh <henrik.blidh@nedomkull.com>
Updated on 2020-08-05 by GilShoshan94
"""

import asyncio
import platform

from bleak import BleakClient


async def print_services(mac_addr: str):
    async with BleakClient(mac_addr, timeout=5.0) as client:
        svcs = await client.get_services()
        # print("Obj: ", type(svcs))  # <class 'bleak.backends.service.BleakGATTServiceCollection'>
        # print("Services: ", type(svcs.services))  # <class 'dict'>
        # print("Characteristic: ", type(svcs.characteristics))  # <class 'dict'>
        # print("Descriptors: ", type(svcs.descriptors))  # <class 'dict'>
        print(get_infos(svcs))


def get_infos(svcs):
    sp = "   "  # space indent
    spm = "- "  # space indent with mark
    separator = f"{'_'*70}\n"  # separator between services
    res = separator
    for serv in svcs.services.values():
        res += (
            f"{spm}Service UUID: {serv.uuid} :\n"
            f"{sp*1}Description: {serv.description}\n"
            f"{sp*1}Characteristics: ({len(serv.characteristics)})\n"
        )
        for char in serv.characteristics:
            res += (
                f"\n{sp*1}{spm}Characteristic UUID: {char.uuid} :\n"
                f"{sp*2}Description: {char.description}\n"
                f"{sp*2}Handle: {char.handle}\n"
                f"{sp*2}Properties: {char.properties}\n"
                f"{sp*2}Descriptiors: ({len(char.descriptors)})\n"
            )
            for desc in char.descriptors:
                res += (
                    f"\n{sp*2}{spm}Descriptor UUID: {desc.uuid}\n"
                    f"{sp*3}Description: {desc.description}\n"
                    f"{sp*3}Handle: {desc.handle}\n"
                )

        res += separator
    return res


if __name__ == "__main__":
    # Change to your device's address here if you are using Windows or Linux or Mac
    address = "7F:2E:03:F1:2C:1E" if platform.system() != "Darwin" else "B9EA5233-37EF-4DD6-87A8-2A875E821C46"
    loop = asyncio.get_event_loop()
    loop.run_until_complete(print_services(address))

And when I tried it on my BLE headset (I had to higher the timeout to 5.0) this is the result:

______________________________________________________________________
- Service UUID: 0000febe-0000-1000-8000-00805f9b34fb :
   Description: Bose Corporation
   Characteristics: (4)

   - Characteristic UUID: 9ec813b4-256b-4090-93a8-a4f0e9107733 :
      Description:
      Handle: 2
      Properties: ['read', 'notify']
      Descriptiors: (1)

      - Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb
         Description: Client Characteristic Configuration
         Handle: 4

   - Characteristic UUID: d417c028-9818-4354-99d1-2ac09d074591 :
      Description:
      Handle: 5
      Properties: ['read', 'write-without-response', 'write', 'notify']
      Descriptiors: (1)

      - Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb
         Description: Client Characteristic Configuration
         Handle: 7

   - Characteristic UUID: c65b8f2f-aee2-4c89-b758-bc4892d6f2d8 :
      Description:
      Handle: 8
      Properties: ['read', 'write-without-response', 'write', 'notify']
      Descriptiors: (1)

      - Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb
         Description: Client Characteristic Configuration
         Handle: 10

   - Characteristic UUID: 234bfbd5-e3b3-4536-a3fe-723620d4b78d :
      Description:
      Handle: 11
      Properties: ['write']
      Descriptiors: (0)
______________________________________________________________________
- Service UUID: 00001801-0000-1000-8000-00805f9b34fb :
   Description: Generic Attribute Profile
   Characteristics: (1)

   - Characteristic UUID: 00002a05-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 14
      Properties: ['indicate']
      Descriptiors: (1)

      - Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb
         Description: Client Characteristic Configuration
         Handle: 16
______________________________________________________________________
- Service UUID: 00001800-0000-1000-8000-00805f9b34fb :
   Description: Generic Access Profile
   Characteristics: (2)

   - Characteristic UUID: 00002a00-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 18
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a01-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 20
      Properties: ['read']
      Descriptiors: (0)
______________________________________________________________________
- Service UUID: 0000180a-0000-1000-8000-00805f9b34fb :
   Description: Device Information
   Characteristics: (8)

   - Characteristic UUID: 00002a29-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 23
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a24-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 25
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a25-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 27
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a27-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 29
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a26-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 31
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a28-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 33
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a23-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 35
      Properties: ['read']
      Descriptiors: (0)

   - Characteristic UUID: 00002a50-0000-1000-8000-00805f9b34fb :
      Description:
      Handle: 37
      Properties: ['read']
      Descriptiors: (0)
______________________________________________________________________

Which I think is more useful. This example also shows some of the properties available.

Again thank you so much for this library. I am continuing to explore it, if it is welcomed, I can share more useful example as I am writing some utilities for myself. Let me know.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
GilShoshan94commented, Aug 5, 2020

Never mind, just saw to service_explorer.py example… I mist it. I close this.

0reactions
GilShoshan94commented, Aug 10, 2020

@hbldh I forgot the f-string was introduced in 3.6. sorry about that… I tried it here with .format() . I am very new to async (I started learning it because your library use it).

We can still do a version without await for the __str__, we simply don’t request the value (But we lose it…). Like that (in bleak\backends\service.py in the class BleakGATTService):

def __str__(self) -> str:
    """
    Extracts the all the infos for a report.
    """
    sp = "    "  # space indent
    separator = "{0}\n".format('_'*200)  # separator between services
    result = separator
    for serv in self.services.values():
        result += "[Service] {0} : {1}\n".format(serv.uuid, serv.description)
        for char in serv.characteristics:
            prop = "({0})".format(','.join(char.properties))
            result += (
                "{0}[Characteristic] {1} : (Handle: {2:<3}) ".format(sp, char.uuid, char.handle)
                "{0:<42} | Name: {1:<40}\n".format(prop, char.description)
            )
            for desc in char.descriptors:
                result += (
                    "{0}[Descriptor] {1} : (Handle: {2:<3}) ".format(sp*2, desc.uuid, desc.handle)
                    "{0:<42} | Name: {1:<40}\n".format('', desc.description)
                )
        result += separator
    return result 

And the result should look like that:

...
________________________________________________________________________________________________________________________________________________________________________________________________________
[Service] 00001801-0000-1000-8000-00805f9b34fb : Generic Attribute Profile
    [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb : (Handle: 14 ) (indicate)                                 | Name:                        
        [Descriptor] 00002902-0000-1000-8000-00805f9b34fb : (Handle: 16 )                                            | Name: Client Characteristic Configuration
________________________________________________________________________________________________________________________________________________________________________________________________________
[Service] 00001800-0000-1000-8000-00805f9b34fb : Generic Access Profile
    [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb : (Handle: 18 ) (read)                                     | Name:                
    [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb : (Handle: 20 ) (read)                                     | Name:                 
________________________________________________________________________________________________________________________________________________________________________________________________________
...

I tried to convert the f-string to str.format() I did not test this code.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Getting Started | Google Ads API
Create a GoogleAdsClient instance. The most important classes in the Google Ads API .NET library is the GoogleAdsClient class. It lets you create...
Read more >
Minimal APIs quick reference - Microsoft Learn
Provides an overview of minimal APIs in ASP.NET Core.
Read more >
Implement Repository & Unit of Work patterns in .NET Core ...
Practical examples of how to implement a repository and unit of work design pattern in a typical .NET core project to solve all...
Read more >
Java 14 Features (with Examples) - HappyCoders.eu
Java 14 features with examples: Switch Expressions, Helpful NullPointerExceptions, Previews: Records + Pattern matching for instanceof + ...
Read more >
Want Something? Pull a Trigger - ActiveState
Enter Komodo's agile, powerful macro-system to the rescue. You can write macros in either JavaScript or Python. Most of Komodo's front-end code ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found