IanHarvey / bluepy

Python interface to Bluetooth LE on Linux
Other
1.58k stars 490 forks source link

Pairing to a BLE peripheral that has a passkey; needed to pair using Bluepy #451

Open abhishek-v-pandey opened 3 years ago

abhishek-v-pandey commented 3 years ago

Hello Team,

I have a BLE sensor device that requires a passkey to enter in order to get connected. I know the pairing key and the mac-address of the sensor. When I tried to connect using the nRF connect app on my smartphone, I was able to connect to the sensor. But when I tried connecting with the python script using the Bluepy library, it does not connect and throws an error. I also do not see any prompt to connect to it.

I have also tried various methods listed out like using commands

  1. sudo hcitool lescan
  2. sudo gatttool -t random -b -I
  3. sudo gatttool -b -I

Below is my code

import sys
import time
from bluepy import btle

bt_addrs = '00:1e:ae:3d:d8:1c'

def data():

    tp_sensor = btle.Peripheral(bt_addrs)
    tp_sensor.setSecurityLevel(level="high")

    tp_serviceA = tp_sensor.getServiceByUUID("65c4f2e0-b19e-11e2-9e96-0800200c9a66")

    while True:
        time.sleep(2.0)

        read_char1(tp_serviceA)
        print("\n")
        time.sleep(2.0)

def read_char1(sA):
    char1 = sA.getCharacteristics("4020f2e0-b19e-11e2-9e96-0800200c9a66")
    char1_value = char1.read()
    char1_value = byte_array_to_int(char1_value)
    print(" char 1 value = ", char1_value)

def byte_array_to_int(value):
    value = bytearray(value)
    value = int.from_bytes(value, byteorder='little')
    return value

if __name__ == "__main__":
    data()   

Please help as I need to get through this pairing issue so that I can see the data of the sensor. I am using Raspberry Pi 4.

Thanks !

abhishek-v-pandey commented 3 years ago

Hi @ukBaz I tried your solution but it did not work. I am using Raspberry Pi 4. I can connect to the sensor with nRF connect app which allows me to enter the passkey. But with Raspberry Pi it throws an error.

Below is my code.

from threading import Thread
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
import sys
import time
from bluepy import btle

BUS_NAME = 'org.bluez'
ADAPTER_IFACE = 'org.bluez.Adapter1'
ADAPTER_ROOT = '/org/bluez/hci'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
AGENT_PATH = '/my/app/agent'
AGNT_MNGR_PATH = '/org/bluez'
CAPABILITY = 'KeyboardDisplay'
DEVICE_IFACE = 'org.bluez.Device1'
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()

def set_trusted(path):
    props = dbus.Interface(bus.get_object(BUS_NAME, path), dbus.PROPERTIES_IFACE)
    props.Set(DEVICE_IFACE, "Trusted", True)

class Agent(dbus.service.Object):

    @dbus.service.method(AGENT_IFACE,
                         in_signature="", out_signature="")
    def Release(self):
        print("Release")

    @dbus.service.method(AGENT_IFACE,
                         in_signature='o', out_signature='s')
    def RequestPinCode(self, device):
        print(f'RequestPinCode {device}')
        return '0000'

    @dbus.service.method(AGENT_IFACE,
                         in_signature="ou", out_signature="")
    def RequestConfirmation(self, device, passkey):
        print("RequestConfirmation (%s, %06d)" % (device, passkey))
        set_trusted(device)
        return

    @dbus.service.method(AGENT_IFACE,
                         in_signature="o", out_signature="")
    def RequestAuthorization(self, device):
        print("RequestAuthorization (%s)" % (device))
        auth = input("Authorize? (yes/no): ")
        if (auth == "yes"):
            return
        raise Rejected("Pairing rejected")

    @dbus.service.method(AGENT_IFACE,
                         in_signature="o", out_signature="u")
    def RequestPasskey(self, device):
        print("RequestPasskey (%s)" % (device))
        set_trusted(device)
        passkey = input("Enter passkey: ")
        return dbus.UInt32(passkey)

    @dbus.service.method(AGENT_IFACE,
                         in_signature="ouq", out_signature="")
    def DisplayPasskey(self, device, passkey, entered):
        print("DisplayPasskey (%s, %06u entered %u)" %
              (device, passkey, entered))

    @dbus.service.method(AGENT_IFACE,
                         in_signature="os", out_signature="")
    def DisplayPinCode(self, device, pincode):
        print("DisplayPinCode (%s, %s)" % (device, pincode))

class Adapter:
    def __init__(self, idx=0):
        bus = dbus.SystemBus()
        self.path = f'{ADAPTER_ROOT}{idx}'
        self.adapter_object = bus.get_object(BUS_NAME, self.path)
        self.adapter_props = dbus.Interface(self.adapter_object,
                                            dbus.PROPERTIES_IFACE)
        self.adapter_props.Set(ADAPTER_IFACE,
                               'DiscoverableTimeout', dbus.UInt32(0))
        self.adapter_props.Set(ADAPTER_IFACE,
                               'Discoverable', True)
        self.adapter_props.Set(ADAPTER_IFACE,
                               'PairableTimeout', dbus.UInt32(0))
        self.adapter_props.Set(ADAPTER_IFACE,
                               'Pairable', True)

agent = Agent(bus, AGENT_PATH)
manager = dbus.Interface(bus.get_object(BUS_NAME, AGNT_MNGR_PATH), AGNT_MNGR_IFACE)
manager.RegisterAgent(AGENT_PATH, CAPABILITY)
manager.RequestDefaultAgent(AGENT_PATH)
adapter = Adapter()

def run_gbus():
    main_loop = GLib.MainLoop()
    try:
        main_loop.run()
    except KeyboardInterrupt:
        manager.UnregisterAgent(AGENT_PATH)
        main_loop.quit()

t1 = Thread(target = run_gbus)
t1.start()

# after this, I connect and pair with my Peripheral
peripheral = btle.Peripheral('00:1e:ae:3d:d8:1c')
peripheral.connect()
peripheral_A = peripheral.getServiceByUUID("65c4f2e0-b19e-11e2-9e96-0800200c9a66")
print(peripheral_A)

Error : bluepy.btle.BTLEDisconnectError: Failed to connect to peripheral 00:1e:ae:3d:d8:1c, addr type: public

Do you think this makes a difference by the way it connects.? How it connection works with you using bluepy.? Any special code we should write for working with security?

Thanks

leoguanco commented 1 year ago

@abhishek-v-pandey Hi! how are you? Did you find any solution?