About BLE.gap_connect(esp32-based ubluetooth)

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Fri Nov 08, 2019 5:07 am

Hello everyone,
I'm trying the esp32-based ubluetooth library. The example on github is based on the bluetooth library and is not an example of a Central Role (GATT Client).

Code: Select all

BLE.gap_connect (addr_type, addr, scan_duration_ms s 2000)
How to get the addr_type and addr of ble peripheral devices(such as BLE Heart rate band), Make a connection. Is there any example of Central Role (GATT Client)?

Thanks.

User avatar
jimmo
Posts: 878
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by jimmo » Fri Nov 08, 2019 10:21 am

hi,

Yes, sorry, I haven't gotten around to the central role examples yet.

By far the easiest way is to do a scan, and use the address type and address returned during the scan.

Code: Select all

from micropython import const
_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)

def adv_decode(adv_type, data):
    i = 0
    while i + 1 < len(data):
        if data[i + 1] == adv_type:
            return data[i + 2:i + data[i] + 1]
        i += 1 + data[i]
    return None

def adv_decode_name(data):
    n = adv_decode(0x09, data)
    if n:
        return n.decode('utf-8')
    return data

def bt_irq(event, data):
  if event == _IRQ_SCAN_RESULT:
        # A single scan result.
        addr_type, addr, connectable, rssi, adv_data = data
        print(addr_type, addr, adv_decode_name(adv_data))
    elif event == _IRQ_SCAN_COMPLETE:
        # Scan duration finished or manually stopped.
        print('scan complete')

# Scan for 10s (at 100% duty cycle)
ble.gap_scan(10000, 30000, 30000)

User avatar
jimmo
Posts: 878
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by jimmo » Fri Nov 08, 2019 10:22 am

And the address should be printed on the device, so once you know the right address type to use, then you can also just hard-code the address if you want.

I will add some documentation for the address types.

User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Fri Nov 08, 2019 1:11 pm

jimmo wrote:
Fri Nov 08, 2019 10:22 am
And the address should be printed on the device, so once you know the right address type to use, then you can also just hard-code the address if you want.

I will add some documentation for the address types.
jimmo,I will try your code.thanks

User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Fri Nov 08, 2019 3:06 pm

jimmo wrote:
Fri Nov 08, 2019 10:21 am
hi,

Yes, sorry, I haven't gotten around to the central role examples yet.

By far the easiest way is to do a scan, and use the address type and address returned during the scan.

Code: Select all

from micropython import const
_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)

def adv_decode(adv_type, data):
    i = 0
    while i + 1 < len(data):
        if data[i + 1] == adv_type:
            return data[i + 2:i + data[i] + 1]
        i += 1 + data[i]
    return None

def adv_decode_name(data):
    n = adv_decode(0x09, data)
    if n:
        return n.decode('utf-8')
    return data

def bt_irq(event, data):
  if event == _IRQ_SCAN_RESULT:
        # A single scan result.
        addr_type, addr, connectable, rssi, adv_data = data
        print(addr_type, addr, adv_decode_name(adv_data))
    elif event == _IRQ_SCAN_COMPLETE:
        # Scan duration finished or manually stopped.
        print('scan complete')

# Scan for 10s (at 100% duty cycle)
ble.gap_scan(10000, 30000, 30000)
I try this code:

Code: Select all

from ubluetooth import BLE, UUID, FLAG_NOTIFY, FLAG_READ, FLAG_WRITE
from micropython import const
_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)

def adv_decode(adv_type, data):
    i = 0
    while i + 1 < len(data):
        if data[i + 1] == adv_type:
            return data[i + 2:i + data[i] + 1]
        i += 1 + data[i]
    return None

def adv_decode_name(data):
    n = adv_decode(0x09, data)
    if n:
        return n.decode('utf-8')
    return data

def bt_irq(event, data):
  if event == _IRQ_SCAN_RESULT:
    # A single scan result.
    addr_type, addr, connectable, rssi, adv_data = data
    print(addr_type, addr, adv_decode_name(adv_data))
  elif event == _IRQ_SCAN_COMPLETE:
    # Scan duration finished or manually stopped.
    print('scan complete')

# Scan for 10s (at 100% duty cycle)
bt = BLE()
bt.active(True)
bt.gap_scan(10000, 30000, 30000)
It not begin scan.
MicroPython v1.11-571-g7e374d231 on 2019-11-08; ESP32 module with ESP32

User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Fri Nov 08, 2019 3:33 pm

>>> exec(open('./hrm1107.py').read(),globals())
GAP procedure initiated: stop advertising.
GAP procedure initiated: discovery; own_addr_type=0 filter_policy=0 passive=1 limited=0 filter_duplicates=0 duration=10000ms

User avatar
jimmo
Posts: 878
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by jimmo » Fri Nov 08, 2019 9:16 pm

I forgot, you also need to set the irq

Code: Select all

bt.irq(handler=br_irq)

User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Sat Nov 09, 2019 1:23 am

It works.

Code: Select all

>>> %Run -c $EDITOR_CONTENT
>>> 0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'
0 b'\xf4^\xab\x91k\x97' b'\x02\x01\x06\x05\x02\r\x18\x0f\x18'

Code: Select all

    elif event == _IRQ_SCAN_RESULT:
        # A single scan result.
        addr_type, addr, connectable, rssi, adv_data = data
So,
addr_type= 0
addr = b'\xf4^\xab\x91k\x97'

I will try,thank you.

User avatar
net0040
Posts: 26
Joined: Fri Nov 08, 2019 4:33 am

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by net0040 » Sat Nov 09, 2019 11:23 am

I try connect a BLE heartRate band with esp32。
code below:

Code: Select all

#2019-11-09

from ubluetooth import BLE, UUID, FLAG_NOTIFY, FLAG_READ, FLAG_WRITE
from micropython import const
_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)
_IRQ_PERIPHERAL_CONNECT              = const(1 << 6)
_IRQ_PERIPHERAL_DISCONNECT           = const(1 << 7)
_IRQ_GATTC_SERVICE_RESULT            = const(1 << 8)
_IRQ_GATTC_CHARACTERISTIC_RESULT     = const(1 << 9)
_IRQ_GATTC_DESCRIPTOR_RESULT         = const(1 << 10)
_IRQ_GATTC_READ_RESULT               = const(1 << 11)
_IRQ_GATTC_WRITE_STATUS              = const(1 << 12)

def adv_decode(adv_type, data):
    i = 0
    while i + 1 < len(data):
        if data[i + 1] == adv_type:
            return data[i + 2:i + data[i] + 1]
        i += 1 + data[i]
    return None

def adv_decode_name(data):
    n = adv_decode(0x09, data)
    if n:
        return n.decode('utf-8')
    return data

def bt_irq(event, data):
  if event == _IRQ_SCAN_RESULT:
    # A single scan result.
    addr_type, addr, connectable, rssi, adv_data = data
    print(addr_type, addr, connectable,adv_decode_name(adv_data))
  elif event == _IRQ_SCAN_COMPLETE:
    # Scan duration finished or manually stopped.
    print('scan complete')
  elif event == _IRQ_PERIPHERAL_CONNECT:
    # A successful gap_connect().
    conn_handle, addr_type, addr = data
    print('conn_handle','addr_type','addr')
    print(conn_handle,addr_type,addr)
    print('conn complete')
  elif event == _IRQ_PERIPHERAL_DISCONNECT:
    # Connected peripheral has disconnected.
    conn_handle, addr_type, addr = data
  elif event == _IRQ_GATTC_SERVICE_RESULT:
    # Called for each service found by gattc_discover_services().
    conn_handle, start_handle, end_handle, uuid = data
    print(start_handle, end_handle)
    print('GATTC_SERVICE ok')
  elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
    # Called for each characteristic found by gattc_discover_services().
    conn_handle, def_handle, value_handle, properties, uuid = data
    print(value_handle,uuid)
  elif event == _IRQ_GATTC_DESCRIPTOR_RESULT:
    # Called for each descriptor found by gattc_discover_descriptors().
    conn_handle, dsc_handle, uuid = data
  elif event == _IRQ_GATTC_READ_RESULT:
    # A gattc_read() has completed.
    conn_handle, value_handle, char_data = data
    print(value_handle, char_data)
  elif event == _IRQ_GATTC_WRITE_STATUS:
    # A gattc_write() has completed.
    conn_handle, value_handle, status = data

# Scan for 10s (at 100% duty cycle)
bt = BLE()
bt.active(True)
bt.irq(handler=bt_irq)
#bt.gap_scan(10000, 30000, 30000)
bt.gap_connect(0, b'\xf4^\xab\x91k\x97', 2000)
bt.gattc_discover_services(0)
result below

Code: Select all

MicroPython v1.11-571-g7e374d231 on 2019-11-08; ESP32 module with ESP32

Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
  File "<stdin>", line 73, in <module>
OSError: [Errno 107] ENOTCONN
>>> conn_handle addr_type addr
0 0 b'\xf4^\xab\x91k\x97'
conn complete
Thonny Ide v3.2.3
Q:what is wrong with: bt.gattc_discover_services(0)
I want to use

Code: Select all

  bt.gattc_discover_services(conn_handle) 
Query a connected peripheral(ble heart rate band) for its heart rate service.

thanks.

User avatar
jimmo
Posts: 878
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: About BLE.gap_connect(esp32-based ubluetooth)

Post by jimmo » Sun Nov 10, 2019 11:48 pm

You can't discover services until you're connected to the peripheral. i.e. you have to wait until you get the _IRQ_PERIPHERAL_CONNECT event.

If you want a "synchronous" connect, you might find this thread viewtopic.php?f=20&t=7199 and followup in this thread viewtopic.php?f=2&t=7205 useful.

Post Reply