SimplePyBLE - Python bindings for SimpleBLE

Overview

SimplePyBLE - Python bindings for SimpleBLE

The ultimate fully-fledged cross-platform BLE library, designed for simplicity and ease of use.

All specific operating system quirks are handled to provide a consistent behavior across all platforms. Each major version of the library will have a stable API that will be fully forwards compatible.

If you want to use the library and need help. Please reach out! You can find me at: kevin at dewald dot me

Instalation

pip install simplepyble

Usage

Please review the provided examples in the source code. They are all self-contained and can be run from the command line. More documentation will be available soon.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

All components within this project that have not been bundled from external creators, are licensed under the terms of the MIT Licence.

Comments
  • Repeated read gives always the same value

    Repeated read gives always the same value

    It seems that reading value from characteristic from peripheral never gets updated during one connection, multiple reads during the same connection always give me the same value, even when the characteristic is updated on the service side. I did a test, I created a peripheral with service with 2 text characteristics, A for writing and B for reading. On the service side, when A is written , B is updated. When I do the the connection to this peripheral and then the sequence: write - read - write different value - read, the second read gives me the value from the first read, it never gets updated. When I disconnect from peripheral and connect again, read gives me updated second value. Is this a "feature" or the bug?

    opened by piotromt 11
  • peripheral.identifier() in the scan example always return an empty string.

    peripheral.identifier() in the scan example always return an empty string.

    I am running the scan.py example on windows 10 pro, Python 3.9.5. Everything works well except that the device names are not printed. I think it's supposed to come from peripheral.identifier() but it seems to return an empty string for all devices.

    By device name I mean the human friendly name that we see in the bluetooth device setting screens of Windows, iPhone, etc.

    opened by zapta 5
  • Please expose the pairing related methods in the Python API

    Please expose the pairing related methods in the Python API

    These two pairing related methods are not reflected in the Python API.

    Please add them there.

    https://github.com/OpenBluetoothToolbox/SimpleBLE/blob/main/include/simpleble/Peripheral.h#L32

    opened by zapta 3
  • peripheral.read: UnicodeDecodeError: 'utf-8' codec can't decode byte

    peripheral.read: UnicodeDecodeError: 'utf-8' codec can't decode byte

    Windows 10; python 3.9.7

    import simplepyble
    import random
    import threading
    import time
    from Crypto.Cipher import AES
    from Crypto.Random import get_random_bytes
    
    def encrypt(key, data):
      k = AES.new(bytes(reversed(key)), AES.MODE_ECB)
      data = reversed(list(k.encrypt(bytes(reversed(data)))))
      rev = []
      for d in data:
        rev.append(d)
      return rev
    
    
    def key_encrypt(name, password, key):
      name = name.ljust(16, chr(0))
      password = password.ljust(16, chr(0))
      data = [ord(a) ^ ord(b) for a,b in zip(name,password)]
      return encrypt(key, data)
    
    class dimond:
      def __init__(self, vendor, mac, name, password, mesh=None, callback=None):
        self.vendor = vendor
        self.mac = mac
        self.macarray = mac.split(':')
        self.name = name
        self.password = password
        self.callback = callback
        self.mesh = mesh
        self.packet_count = random.randrange(0xffff)
        self.macdata = [int(self.macarray[5], 16), int(self.macarray[4], 16), int(self.macarray[3], 16), int(self.macarray[2], 16), int(self.macarray[1], 16), int(self.macarray[0], 16)]
      
      def __done__(self):
        self.peripheral.disconnect()
    
      def set_sk(self, sk):
        self.sk = sk
    
      def connect(self):
        #self.device = btle.Peripheral(self.mac, addrType=btle.ADDR_TYPE_PUBLIC)
        adapters = simplepyble.Adapter.get_adapters()
    
        if len(adapters) == 0:
            print("No adapters found")
    
        # Query the user to pick an adapter
        adapter = adapters[0]
    
        print(f"Selected adapter: {adapter.identifier()} [{adapter.address()}]")
    
        adapter.set_callback_on_scan_start(lambda: print("Scan started."))
        adapter.set_callback_on_scan_stop(lambda: print("Scan complete."))
        adapter.set_callback_on_scan_found(lambda peripheral: (peripheral.address() == self.mac) and print(f"Found {peripheral.identifier()} [{peripheral.address()}]"))
    
        # Scan for 5 seconds
        adapter.scan_for(5000)
        peripherals = adapter.scan_get_results()
        
        self.peripheral = None
        # Query the user to pick a peripheral
        for i, p in enumerate(peripherals):
            if p.address() == self.mac:
                self.peripheral = p
                break
    
        if (self.peripheral):
            connectable_str = "Connectable" if self.peripheral.is_connectable() else "Non-Connectable"
            print(f"{self.peripheral.identifier()} [{self.peripheral.address()}] - {connectable_str}")
    
            manufacturer_data = self.peripheral.manufacturer_data()
            for manufacturer_id, value in manufacturer_data.items():
                print(f"    Manufacturer ID: {manufacturer_id}")
                print(f"    Manufacturer data: {value}")
    
            print(f"Connecting to: {self.peripheral.identifier()} [{self.peripheral.address()}]")
            self.peripheral.connect()
            '''
            print("Successfully connected, listing services...")
            services = self.peripheral.services()
            for service in services:
                print(f"Service: {service.uuid}")
                for characteristic in service.characteristics:
                    print(f"    Characteristic: {characteristic}")
            '''
            self.notification = '00010203-0405-0607-0809-0a0b0c0d1911'
            self.control = '00010203-0405-0607-0809-0a0b0c0d1912'
            self.pairing = '00010203-0405-0607-0809-0a0b0c0d1914'
           
            data = [0] * 16
            random_data = get_random_bytes(8)
            for i in range(8):
              data[i] = random_data[i]
            enc_data = key_encrypt(self.name, self.password, data)
            packet = [0x0c]
            packet += data[0:8]
            packet += enc_data[0:8]
            try:
              self.peripheral.write_request('00010203-0405-0607-0809-0a0b0c0d1910', self.pairing, bytes(packet))
              time.sleep(0.3)
              data2 = self.peripheral.read('00010203-0405-0607-0809-0a0b0c0d1910', self.pairing)
            except:
              raise Exception("Unable to connect")
            
            print('Ok!')
    
        else:
            print('BT device "{}" not found!'.format(target_mac))
    
    target_mac = '08:65:f0:04:04:e1'
    
    if __name__ == "__main__":
        network = dimond(0x0211, target_mac, "ZenggeMesh", "ZenggeTechnology")#, callback=callback)
        network.connect()
    
    (base) D:\work\btdimmer>python btdimmer.py
    Selected adapter: dongle [00:1a:7d:da:71:12]
    Scan started.
    Found abd8302448845239 [08:65:f0:04:04:e1]
    Scan complete.
    abd8302448845239 [08:65:f0:04:04:e1] - Connectable
        Manufacturer ID: 529
        Manufacturer data: b'\x11\x02\xe1\x04\x04\xf0\x02\x0f\x01\x02\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
    Connecting to: abd8302448845239 [08:65:f0:04:04:e1]
    Traceback (most recent call last):
      File "D:\work\btdimmer\btdimmer.py", line 109, in connect
        data2 = self.peripheral.read('00010203-0405-0607-0809-0a0b0c0d1910', self.pairing)
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 1: invalid start byte
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "D:\work\btdimmer\btdimmer.py", line 122, in <module>
        network.connect()
      File "D:\work\btdimmer\btdimmer.py", line 111, in connect
        raise Exception("Unable to connect")
    Exception: Unable to connect
    
    (base) D:\work\btdimmer>
    
    opened by zenbooster 2
  • How to pair with BLE device?

    How to pair with BLE device?

    Hi, I am using Library "simplepyble". It is looking very simple and easy to use but I didn't find any method or syntax for pairing or bonding in the examples. Can you please guide me on how I can pair my PC with my BLE device using "simplepyble". Thanks.

    opened by inamghouss 1
  • run example scan.py error: Process finished with exit code -1073741819 (0xC0000005)

    run example scan.py error: Process finished with exit code -1073741819 (0xC0000005)

    some details window10 python => 3.8.5 simplepyble => 0.0.5

    sometimes return an empty string for all devices, sometimes return error Process finished with exit code -1073741819 (0xC0000005)

    opened by fanleung 0
Releases(v0.0.5)
  • v0.0.5(Jun 13, 2022)

    [0.0.5] - 2022-06-12

    Added

    • Python's Global Interpreter Lock (GIL) will be released during Peripheral.connect()
    • Keep-alive policies for function objects passed into SimplePyBLE.
    Source code(tar.gz)
    Source code(zip)
  • v0.0.4(Feb 14, 2022)

  • v0.0.3(Feb 13, 2022)

    [0.0.3] - 2022-01-22

    Fixed

    • write_request and write_command functions would accept strings instead of bytes as payloads. (Thanks kaedenbrinkman!)
    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(Jan 16, 2022)

  • v0.0.1(Jan 11, 2022)

Owner
Open Bluetooth Toolbox
Tools and code for Bluetooth development
Open Bluetooth Toolbox
Multifunctional Analysis of Regions through Input-Output

MARIO Multifunctional Analysis of Regions through Input-Output. (Documents) What is it MARIO is a python package for handling input-output tables and

14 Dec 25, 2022
Generates Windows 95 and 95 OEM keys using the modulus 7 check algorithm

w95keygen-python windowskeygen.py - Generates Windows 95 and 95 OEM keys using the modulus 7 check algorithm Just download and drop in the directory y

Joshua Alto 1 Dec 06, 2021
The git for the Python Story Utility Package library.

PSUP, The Python Story Utility Package Module. PSUP helps making stories or games with options, diverging paths, different endings and so on. You can

Enoki 6 Nov 27, 2022
Scalene: a high-performance, high-precision CPU, GPU, and memory profiler for Python

Scalene: a high-performance CPU, GPU and memory profiler for Python by Emery Berger, Sam Stern, and Juan Altmayer Pizzorno. Scalene community Slack Ab

PLASMA @ UMass 7k Dec 30, 2022
Simple project to learn more about Bézier curves

Python Quadratic Bézier Simple project to learn more about Bézier curves. On this project i used some api's to graphics and gui pygame thorpy in theor

Kenned Ferreira 2 Mar 06, 2022
a sketch of what a zkvm could look like

We want to build a ZKP that validates an entire EVM block or as much of it as we can efficiently. Its okay to adjust the gas costs for every EVM opcode. Its also to exclude some opcodes for now if th

25 Dec 30, 2022
Integration of Hotwire's Turbo library with Flask.

turbo-flask Integration of Hotwire's Turbo library with Flask, to allow you to create applications that look and feel like single-page apps without us

Miguel Grinberg 240 Jan 06, 2023
A repository of study materials related to Think Python 2nd Edition by Allen B. Downey. More information about the book can be found here: https://greenteapress.com/wp/think-python-2e/

Intro-To-Python This content is based on the book Think Python 2nd Edition by Allen B. Downey. More information about the book can be found here: http

Brent Eskridge 63 Jan 07, 2023
Contain the customization I made for my Linux rice.

dotfiles Contain the customization I made for my Linux rice. Credit and Respect Polybar Autohide Fulltime Rofi by adi1090x (only include my personal r

sora 3 Apr 04, 2022
Run PD patches in NRT using Python

The files in this repository demonstrate how to use Pure Data (Pd) patches designed to run in Non-Real-Time mode to batch-process (synthesize, analyze, etc) sounds in series using Python.

Jose Henrique Padovani 3 Feb 08, 2022
Scientific Programming: A Crash Course

Scientific Programming: A Crash Course Welcome to the Scientific Programming course. My name is Jon Carr and I am a postdoc in Davide Crepaldi's lab.

Jon Carr 1 Feb 17, 2022
Headless chatbot that detects spam and posts links to it to chatrooms for quick deletion.

SmokeDetector Headless chatbot that detects spam and posts it to chatrooms. Uses ChatExchange, takes questions from the Stack Exchange realtime tab, a

Charcoal 421 Dec 21, 2022
30DaysOfCode-PhoenixClub - Solution of everyday coding problem given in 30DaysofCode contest held on Hackerrank

30DaysOfCode-PhoenixClub 👨‍💻 Every day problems solution given in 30DaysOfCode

Urveshkumar 8 Jan 30, 2022
These are the scripts used for the project of ‘Assembly of a pan-genome for global cattle reveals missing sequence and novel structural variation, providing new insights into their diversity and evolution history’

script-SV-genotyping These are the scripts used for the project of ‘Assembly of a pan-genome for global cattle reveals missing sequence and novel stru

2 Aug 26, 2022
A Python wrapper for Matrix Synapse admin API

Synapse-admin-api-python A Python wrapper for Matrix Synapse admin API. Versioning This library now supports up to Synapse 1.45.0, any Admin API intro

Knugi 9 Sep 28, 2022
Your one and only Discord Bot that helps you concentrate!

Your one and only Discord Bot thats helps you concentrate! Consider leaving a ⭐ if you found the project helpful. concy-bot A bot which constructively

IEEE VIT Student Chapter 22 Sep 27, 2022
Implementation of the Folders📂 esoteric programming language, a language with no code and just folders.

Folders.py Folders is an esoteric programming language, created by Daniel Temkin in 2015, which encodes the program entirely into the directory struct

Sina Khalili 425 Dec 17, 2022
A Brainfuck interpreter written in Python.

A Brainfuck interpreter written in Python.

Ethan Evans 1 Dec 05, 2021
An easy FASTA object handler, reader, writer and translator for small to medium size projects without dependencies.

miniFASTA An easy FASTA object handler, reader, writer and translator for small to medium size projects without dependencies. Installation Using pip /

Jules Kreuer 3 Jun 30, 2022
SECRET SANTA / KRIS KINGLE

SECRET SANTA / KRIS KINGLE Note: Before executing the script, make sure to turn

DEV_FINWIZ 10 Dec 06, 2022