1# Test BLE GAP connect/disconnect
2
3from micropython import const
4import time, machine, bluetooth
5
6TIMEOUT_MS = 5000
7
8_IRQ_CENTRAL_CONNECT = const(1)
9_IRQ_CENTRAL_DISCONNECT = const(2)
10_IRQ_PERIPHERAL_CONNECT = const(7)
11_IRQ_PERIPHERAL_DISCONNECT = const(8)
12_IRQ_GATTC_SERVICE_RESULT = const(9)
13_IRQ_GATTC_SERVICE_DONE = const(10)
14
15UUID_A = bluetooth.UUID(0x180D)
16UUID_B = bluetooth.UUID("A5A5A5A5-FFFF-9999-1111-5A5A5A5A5A5A")
17SERVICE_A = (
18    UUID_A,
19    (),
20)
21SERVICE_B = (
22    UUID_B,
23    (),
24)
25SERVICES = (SERVICE_A, SERVICE_B)
26
27waiting_events = {}
28num_service_result = 0
29
30
31def irq(event, data):
32    global num_service_result
33    if event == _IRQ_CENTRAL_CONNECT:
34        print("_IRQ_CENTRAL_CONNECT")
35        waiting_events[event] = data[0]
36    elif event == _IRQ_CENTRAL_DISCONNECT:
37        print("_IRQ_CENTRAL_DISCONNECT")
38    elif event == _IRQ_PERIPHERAL_CONNECT:
39        print("_IRQ_PERIPHERAL_CONNECT")
40        waiting_events[event] = data[0]
41    elif event == _IRQ_PERIPHERAL_DISCONNECT:
42        print("_IRQ_PERIPHERAL_DISCONNECT")
43    elif event == _IRQ_GATTC_SERVICE_RESULT:
44        if data[3] == UUID_A or data[3] == UUID_B:
45            print("_IRQ_GATTC_SERVICE_RESULT", data[3])
46            num_service_result += 1
47    elif event == _IRQ_GATTC_SERVICE_DONE:
48        print("_IRQ_GATTC_SERVICE_DONE")
49
50    if event not in waiting_events:
51        waiting_events[event] = None
52
53
54def wait_for_event(event, timeout_ms):
55    t0 = time.ticks_ms()
56    while time.ticks_diff(time.ticks_ms(), t0) < timeout_ms:
57        if event in waiting_events:
58            return waiting_events.pop(event)
59        machine.idle()
60    raise ValueError("Timeout waiting for {}".format(event))
61
62
63# Acting in peripheral role.
64def instance0():
65    multitest.globals(BDADDR=ble.config("mac"))
66    ble.gatts_register_services(SERVICES)
67    print("gap_advertise")
68    ble.gap_advertise(20_000, b"\x02\x01\x06\x04\xffMPY")
69    multitest.next()
70    try:
71        wait_for_event(_IRQ_CENTRAL_CONNECT, TIMEOUT_MS)
72        wait_for_event(_IRQ_CENTRAL_DISCONNECT, TIMEOUT_MS)
73    finally:
74        ble.active(0)
75
76
77# Acting in central role.
78def instance1():
79    multitest.next()
80    try:
81        # Connect to peripheral and then disconnect.
82        print("gap_connect")
83        ble.gap_connect(*BDADDR)
84        conn_handle = wait_for_event(_IRQ_PERIPHERAL_CONNECT, TIMEOUT_MS)
85
86        # Discover services.
87        ble.gattc_discover_services(conn_handle)
88        wait_for_event(_IRQ_GATTC_SERVICE_DONE, TIMEOUT_MS)
89
90        print("discovered:", num_service_result)
91
92        # Disconnect from peripheral.
93        print("gap_disconnect:", ble.gap_disconnect(conn_handle))
94        wait_for_event(_IRQ_PERIPHERAL_DISCONNECT, TIMEOUT_MS)
95    finally:
96        ble.active(0)
97
98
99ble = bluetooth.BLE()
100ble.active(1)
101ble.irq(irq)
102