# `bluetooth` — low-level Bluetooth

This module provides an interface to a Bluetooth controller on a board. Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, Broadcaster, and Observer roles, as well as GATT Server and Client and L2CAP connection-oriented-channels. A device may operate in multiple roles concurrently. Pairing (and bonding) is supported on some ports.

This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types.

Note

For most applications, we recommend using the higher-level aioble library.

Note

This module is still under development and its classes, functions, methods and constants are subject to change.

## class BLE

## Constructor

class bluetooth.BLE

  Returns the singleton BLE object.

## Configuration

BLE.active([active, ]/)

  Optionally changes the active state of the BLE radio, and returns the current state.

  The radio must be made active before using any other methods on this class.

BLE.config('param', /)
BLE.config(*, param=value, ...)

  Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time.

  Currently supported values are:

  - `'mac'`: The current address in use, depending on the current address mode. This returns a tuple of `(addr_type, addr)`.

    See `gatts_write` for details about address type.

    This may only be queried while the interface is currently active.

  - `'addr_mode'`: Sets the address mode. Values can be:

    > - 0x00 - PUBLIC - Use the controller’s public address.

    > - 0x01 - RANDOM - Use a generated static address.

    > - 0x02 - RPA - Use resolvable private addresses.

    > - 0x03 - NRPA - Use non-resolvable private addresses.

    By default the interface mode will use a PUBLIC address if available, otherwise it will use a RANDOM address.

  - `'gap_name'`: Get/set the GAP device name used by service 0x1800, characteristic 0x2a00. This can be set at any time and changed multiple times.

  - `'rxbuf'`: Get/set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability to receive larger characteristic values.

  - `'mtu'`: Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the minimum of this and the remote device’s MTU. ATT MTU exchange will not happen automatically (unless the remote device initiates it), and must be manually initiated with `gattc_exchange_mtu`. Use the `_IRQ_MTU_EXCHANGED` event to discover the MTU for a given connection.

  - `'bond'`: Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the “bond” flag and the keys will be stored by both devices.

  - `'mitm'`: Sets whether MITM-protection is required for pairing.

  - `'io'`: Sets the I/O capabilities of this device.

    Available options are:

        _IO_CAPABILITY_DISPLAY_ONLY = const(0)
        _IO_CAPABILITY_DISPLAY_YESNO = const(1)
        _IO_CAPABILITY_KEYBOARD_ONLY = const(2)
        _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3)
        _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4)

  - `'le_secure'`: Sets whether “LE Secure” pairing is required. Default is false (i.e. allow “Legacy Pairing”).

## Event Handling

BLE.irq(handler, /)

  Registers a callback for events from the BLE stack. The handler takes two arguments, `event` (which will be one of the codes below) and `data` (which is an event-specific tuple of values).

  Note: As an optimisation to prevent unnecessary allocations, the `addr`, `adv_data`, `char_data`, `notify_data`, and `uuid` entries in the tuples are read-only memoryview instances pointing to `bluetooth`’s internal ringbuffer, and are only valid during the invocation of the IRQ handler function. If your program needs to save one of these values to access after the IRQ handler has returned (e.g. by saving it in a class instance or global variable), then it needs to take a copy of the data, either by using `bytes()` or `bluetooth.UUID()`, like this:

      connected_addr = bytes(addr)  # equivalently: adv_data, char_data, or notify_data
      matched_uuid = bluetooth.UUID(uuid)

  For example, the IRQ handler for a scan result might inspect the `adv_data` to decide if it’s the correct device, and only then copy the address data to be used elsewhere in the program. And to print data from within the IRQ handler, `print(bytes(addr))` will be needed.

  An event handler showing all possible events:

      def bt_irq(event, data):
          if event == _IRQ_CENTRAL_CONNECT:
              # A central has connected to this peripheral.
              conn_handle, addr_type, addr = data
          elif event == _IRQ_CENTRAL_DISCONNECT:
              # A central has disconnected from this peripheral.
              conn_handle, addr_type, addr = data
          elif event == _IRQ_GATTS_WRITE:
              # A client has written to this characteristic or descriptor.
              conn_handle, attr_handle = data
          elif event == _IRQ_GATTS_READ_REQUEST:
              # A client has issued a read. Note: this is only supported on STM32.
              # Return a non-zero integer to deny the read (see below), or zero (or None)
              # to accept the read.
              conn_handle, attr_handle = data
          elif event == _IRQ_SCAN_RESULT:
              # A single scan result.
              addr_type, addr, adv_type, rssi, adv_data = data
          elif event == _IRQ_SCAN_DONE:
              # Scan duration finished or manually stopped.
              pass
          elif event == _IRQ_PERIPHERAL_CONNECT:
              # A successful gap_connect().
              conn_handle, addr_type, addr = data
          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
          elif event == _IRQ_GATTC_SERVICE_DONE:
              # Called once service discovery is complete.
              # Note: Status will be zero on success, implementation-specific value otherwise.
              conn_handle, status = data
          elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
              # Called for each characteristic found by gattc_discover_services().
              conn_handle, end_handle, value_handle, properties, uuid = data
          elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
              # Called once service discovery is complete.
              # Note: Status will be zero on success, implementation-specific value otherwise.
              conn_handle, status = data
          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_DESCRIPTOR_DONE:
              # Called once service discovery is complete.
              # Note: Status will be zero on success, implementation-specific value otherwise.
              conn_handle, status = data
          elif event == _IRQ_GATTC_READ_RESULT:
              # A gattc_read() has completed.
              conn_handle, value_handle, char_data = data
          elif event == _IRQ_GATTC_READ_DONE:
              # A gattc_read() has completed.
              # Note: Status will be zero on success, implementation-specific value otherwise.
              conn_handle, value_handle, status = data
          elif event == _IRQ_GATTC_WRITE_DONE:
              # A gattc_write() has completed.
              # Note: Status will be zero on success, implementation-specific value otherwise.
              conn_handle, value_handle, status = data
          elif event == _IRQ_GATTC_NOTIFY:
              # A server has sent a notify request.
              conn_handle, value_handle, notify_data = data
          elif event == _IRQ_GATTC_INDICATE:
              # A server has sent an indicate request.
              conn_handle, value_handle, notify_data = data
          elif event == _IRQ_GATTS_INDICATE_DONE:
              # A client has acknowledged the indication.
              # Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise.
              conn_handle, value_handle, status = data
          elif event == _IRQ_MTU_EXCHANGED:
              # ATT MTU exchange complete (either initiated by us or the remote device).
              conn_handle, mtu = data
          elif event == _IRQ_L2CAP_ACCEPT:
              # A new channel has been accepted.
              # Return a non-zero integer to reject the connection, or zero (or None) to accept.
              conn_handle, cid, psm, our_mtu, peer_mtu = data
          elif event == _IRQ_L2CAP_CONNECT:
              # A new channel is now connected (either as a result of connecting or accepting).
              conn_handle, cid, psm, our_mtu, peer_mtu = data
          elif event == _IRQ_L2CAP_DISCONNECT:
              # Existing channel has disconnected (status is zero), or a connection attempt failed (non-zero status).
              conn_handle, cid, psm, status = data
          elif event == _IRQ_L2CAP_RECV:
              # New data is available on the channel. Use l2cap_recvinto to read.
              conn_handle, cid = data
          elif event == _IRQ_L2CAP_SEND_READY:
              # A previous l2cap_send that returned False has now completed and the channel is ready to send again.
              # If status is non-zero, then the transmit buffer overflowed and the application should re-send the data.
              conn_handle, cid, status = data
          elif event == _IRQ_CONNECTION_UPDATE:
              # The remote device has updated connection parameters.
              conn_handle, conn_interval, conn_latency, supervision_timeout, status = data
          elif event == _IRQ_ENCRYPTION_UPDATE:
              # The encryption state has changed (likely as a result of pairing or bonding).
              conn_handle, encrypted, authenticated, bonded, key_size = data
          elif event == _IRQ_GET_SECRET:
              # Return a stored secret.
              # If key is None, return the index'th value of this sec_type.
              # Otherwise return the corresponding value for this sec_type and key.
              sec_type, index, key = data
              return value
          elif event == _IRQ_SET_SECRET:
              # Save a secret to the store for this sec_type and key.
              sec_type, key, value = data
              return True
          elif event == _IRQ_PASSKEY_ACTION:
              # Respond to a passkey request during pairing.
              # See gap_passkey() for details.
              # action will be an action that is compatible with the configured "io" config.
              # passkey will be non-zero if action is "numeric comparison".
              conn_handle, action, passkey = data

The event codes are:

    from micropython import const
    _IRQ_CENTRAL_CONNECT = const(1)
    _IRQ_CENTRAL_DISCONNECT = const(2)
    _IRQ_GATTS_WRITE = const(3)
    _IRQ_GATTS_READ_REQUEST = const(4)
    _IRQ_SCAN_RESULT = const(5)
    _IRQ_SCAN_DONE = const(6)
    _IRQ_PERIPHERAL_CONNECT = const(7)
    _IRQ_PERIPHERAL_DISCONNECT = const(8)
    _IRQ_GATTC_SERVICE_RESULT = const(9)
    _IRQ_GATTC_SERVICE_DONE = const(10)
    _IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
    _IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
    _IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
    _IRQ_GATTC_DESCRIPTOR_DONE = const(14)
    _IRQ_GATTC_READ_RESULT = const(15)
    _IRQ_GATTC_READ_DONE = const(16)
    _IRQ_GATTC_WRITE_DONE = const(17)
    _IRQ_GATTC_NOTIFY = const(18)
    _IRQ_GATTC_INDICATE = const(19)
    _IRQ_GATTS_INDICATE_DONE = const(20)
    _IRQ_MTU_EXCHANGED = const(21)
    _IRQ_L2CAP_ACCEPT = const(22)
    _IRQ_L2CAP_CONNECT = const(23)
    _IRQ_L2CAP_DISCONNECT = const(24)
    _IRQ_L2CAP_RECV = const(25)
    _IRQ_L2CAP_SEND_READY = const(26)
    _IRQ_CONNECTION_UPDATE = const(27)
    _IRQ_ENCRYPTION_UPDATE = const(28)
    _IRQ_GET_SECRET = const(29)
    _IRQ_SET_SECRET = const(30)

For the `_IRQ_GATTS_READ_REQUEST` event, the available return codes are:

    _GATTS_NO_ERROR = const(0x00)
    _GATTS_ERROR_READ_NOT_PERMITTED = const(0x02)
    _GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03)
    _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05)
    _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08)
    _GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f)

For the `_IRQ_PASSKEY_ACTION` event, the available actions are:

    _PASSKEY_ACTION_NONE = const(0)
    _PASSKEY_ACTION_INPUT = const(2)
    _PASSKEY_ACTION_DISPLAY = const(3)
    _PASSKEY_ACTION_NUMERIC_COMPARISON = const(4)

In order to save space in the firmware, these constants are not included on the `bluetooth` module. Add the ones that you need from the list above to your program.

## Broadcaster Role (Advertiser)

BLE.gap_advertise(interval_us, adv_data=None, *, resp_data=None, connectable=True)

  Starts advertising at the specified interval (in microseconds). This interval will be rounded down to the nearest 625us. To stop advertising, set interval_us to `None`.

  adv_data and resp_data can be any type that implements the buffer protocol (e.g. `bytes`, `bytearray`, `str`). adv_data is included in all broadcasts, and resp_data is send in reply to an active scan.

  Note: if adv_data (or resp_data) is `None`, then the data passed to the previous call to `gap_advertise` will be re-used. This allows a broadcaster to resume advertising with just `gap_advertise(interval_us)`. To clear the advertising payload pass an empty `bytes`, i.e. `b''`.

## Observer Role (Scanner)

BLE.gap_scan(duration_ms, interval_us=1280000, window_us=11250, active=False, /)

  Run a scan operation lasting for the specified duration (in milliseconds).

  To scan indefinitely, set duration_ms to `0`.

  To stop scanning, set duration_ms to `None`.

  Use interval_us and window_us to optionally configure the duty cycle. The scanner will run for window_us microseconds every interval_us microseconds for a total of duration_ms milliseconds. The default interval and window are 1.28 seconds and 11.25 milliseconds respectively (background scanning).

  For each scan result the `_IRQ_SCAN_RESULT` event will be raised, with event data `(addr_type, addr, adv_type, rssi, adv_data)`.

  `addr_type` values indicate public or random addresses:

    - 0x00 - PUBLIC

    - 0x01 - RANDOM (either static, RPA, or NRPA, the type is encoded in the address itself)

  `adv_type` values correspond to the Bluetooth Specification:

  > - 0x00 - ADV_IND - connectable and scannable undirected advertising

  > - 0x01 - ADV_DIRECT_IND - connectable directed advertising

  > - 0x02 - ADV_SCAN_IND - scannable undirected advertising

  > - 0x03 - ADV_NONCONN_IND - non-connectable undirected advertising

  > - 0x04 - SCAN_RSP - scan response

  `active` can be set `True` if you want to receive scan responses in the results.

  When scanning is stopped (either due to the duration finishing or when explicitly stopped), the `_IRQ_SCAN_DONE` event will be raised.

## Central Role

A central device can connect to peripherals that it has discovered using the observer role (see `gap_scan`) or with a known address.

BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, min_conn_interval_us=None, max_conn_interval_us=None, /)

  Connect to a peripheral.

  See `gap_scan` for details about address types.

  To cancel an outstanding connection attempt early, call `gap_connect(None)`.

  On success, the `_IRQ_PERIPHERAL_CONNECT` event will be raised. If cancelling a connection attempt, the `_IRQ_PERIPHERAL_DISCONNECT` event will be raised.

  The device will wait up to scan_duration_ms to receive an advertising payload from the device.

  The connection interval can be configured in microseconds using either or both of min_conn_interval_us and max_conn_interval_us. Otherwise a default interval will be chosen, typically between 30000 and 50000 microseconds. A shorter interval will increase throughput, at the expense of power usage.

## Peripheral Role

A peripheral device is expected to send connectable advertisements (see `gap_advertise`). It will usually be acting as a GATT server, having first registered services and characteristics using `gatts_register_services`.

When a central connects, the `_IRQ_CENTRAL_CONNECT` event will be raised.

## Central & Peripheral Roles

BLE.gap_disconnect(conn_handle, /)

  Disconnect the specified connection handle. This can either be a central that has connected to this device (if acting as a peripheral) or a peripheral that was previously connected to by this device (if acting as a central).

  On success, the `_IRQ_PERIPHERAL_DISCONNECT` or `_IRQ_CENTRAL_DISCONNECT` event will be raised.

  Returns `False` if the connection handle wasn’t connected, and `True` otherwise.

## GATT Server

A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values.

These values are stored locally, and are accessed by their “value handle” which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can “notify” a characteristic to a connected client via a connection handle.

A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server.

Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use `gatts_write` after registration. e.g. `gatts_write(char_handle, bytes(100))`.

BLE.gatts_register_services(services_definition, /)

  Configures the server with the specified services, replacing any existing services.

  services_definition is a list of services, where each service is a two-element tuple containing a UUID and a list of characteristics.

  Each characteristic is a two-or-three-element tuple containing a UUID, a flags value, and optionally a list of descriptors.

  Each descriptor is a two-element tuple containing a UUID and a flags value.

  The flags are a bitwise-OR combination of the flags defined below. These set both the behaviour of the characteristic (or descriptor) as well as the security and privacy requirements.

  The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened into the same tuple, in the order that they are defined.

  The following example registers two services (Heart Rate, and Nordic UART):

      HR_UUID = bluetooth.UUID(0x180D)
      HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
      HR_SERVICE = (HR_UUID, (HR_CHAR,),)
      UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
      UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
      UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,)
      UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),)
      SERVICES = (HR_SERVICE, UART_SERVICE,)
      ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES)

  The three value handles (`hr`, `tx`, `rx`) can be used with `gatts_read`, `gatts_write`, `gatts_notify`, and `gatts_indicate`.

  Note: Advertising must be stopped before registering services.

  Available flags for characteristics and descriptors are:

      from micropython import const
      _FLAG_BROADCAST = const(0x0001)
      _FLAG_READ = const(0x0002)
      _FLAG_WRITE_NO_RESPONSE = const(0x0004)
      _FLAG_WRITE = const(0x0008)
      _FLAG_NOTIFY = const(0x0010)
      _FLAG_INDICATE = const(0x0020)
      _FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040)

      _FLAG_AUX_WRITE = const(0x0100)
      _FLAG_READ_ENCRYPTED = const(0x0200)
      _FLAG_READ_AUTHENTICATED = const(0x0400)
      _FLAG_READ_AUTHORIZED = const(0x0800)
      _FLAG_WRITE_ENCRYPTED = const(0x1000)
      _FLAG_WRITE_AUTHENTICATED = const(0x2000)
      _FLAG_WRITE_AUTHORIZED = const(0x4000)

  As for the IRQs above, any required constants should be added to your Python code.

BLE.gatts_read(value_handle, /)

  Reads the local value for this handle (which has either been written by `gatts_write` or by a remote client).

BLE.gatts_write(value_handle, data, send_update=False, /)

  Writes the local value for this handle, which can be read by a client.

  If send_update is `True`, then any subscribed clients will be notified (or indicated, depending on what they’re subscribed to and which operations the characteristic supports) about this write.

BLE.gatts_notify(conn_handle, value_handle, data=None, /)

  Sends a notification request to a connected client.

  If data is `None` (the default), then the current local value (as set with `gatts_write`) will be sent.

  Otherwise, if data is not `None`, then that value is sent to the client as part of the notification. The local value will not be modified.

  Note: The notification will be sent regardless of the subscription status of the client to this characteristic.

BLE.gatts_indicate(conn_handle, value_handle, data=None, /)

  Sends a indication request to a connected client.

  If data is `None` (the default), then the current local value (as set with `gatts_write`) will be sent.

  Otherwise, if data is not `None`, then that value is sent to the client as part of the indication. The local value will not be modified.

  On acknowledgment (or failure, e.g. timeout), the `_IRQ_GATTS_INDICATE_DONE` event will be raised.

  Note: The indication will be sent regardless of the subscription status of the client to this characteristic.

BLE.gatts_set_buffer(value_handle, len, append=False, /)

  Sets the internal buffer size for a value in bytes. This will limit the largest possible write that can be received. The default is 20.

  Setting append to `True` will make all remote writes append to, rather than replace, the current value. At most len bytes can be buffered in this way. When you use `gatts_read`, the value will be cleared after reading. This feature is useful when implementing something like the Nordic UART Service.

## GATT Client

A GATT client can discover and read/write characteristics on a remote GATT server.

It is more common for a central role device to act as the GATT client, however it’s also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service).

BLE.gattc_discover_services(conn_handle, uuid=None, /)

  Query a connected server for its services.

  Optionally specify a service uuid to query for that service only.

  For each service discovered, the `_IRQ_GATTC_SERVICE_RESULT` event will be raised, followed by `_IRQ_GATTC_SERVICE_DONE` on completion.

BLE.gattc_discover_characteristics(conn_handle, start_handle, end_handle, uuid=None, /)

  Query a connected server for characteristics in the specified range.

  Optionally specify a characteristic uuid to query for that characteristic only.

  You can use `start_handle=1`, `end_handle=0xffff` to search for a characteristic in any service.

  For each characteristic discovered, the `_IRQ_GATTC_CHARACTERISTIC_RESULT` event will be raised, followed by `_IRQ_GATTC_CHARACTERISTIC_DONE` on completion.

BLE.gattc_discover_descriptors(conn_handle, start_handle, end_handle, /)

  Query a connected server for descriptors in the specified range.

  For each descriptor discovered, the `_IRQ_GATTC_DESCRIPTOR_RESULT` event will be raised, followed by `_IRQ_GATTC_DESCRIPTOR_DONE` on completion.

BLE.gattc_read(conn_handle, value_handle, /)

  Issue a remote read to a connected server for the specified characteristic or descriptor handle.

  When a value is available, the `_IRQ_GATTC_READ_RESULT` event will be raised. Additionally, the `_IRQ_GATTC_READ_DONE` will be raised.

BLE.gattc_write(conn_handle, value_handle, data, mode=0, /)

  Issue a remote write to a connected server for the specified characteristic or descriptor handle.

  The argument mode specifies the write behaviour, with the currently supported values being:

  > - `mode=0` (default) is a write-without-response: the write will be sent to the remote server but no confirmation will be returned, and no event will be raised.

  > - `mode=1` is a write-with-response: the remote server is requested to send a response/acknowledgement that it received the data.

  If a response is received from the remote server the `_IRQ_GATTC_WRITE_DONE` event will be raised.

BLE.gattc_exchange_mtu(conn_handle, /)

  Initiate MTU exchange with a connected server, using the preferred MTU set using `BLE.config(mtu=value)`.

  The `_IRQ_MTU_EXCHANGED` event will be raised when MTU exchange completes.

  Note: MTU exchange is typically initiated by the central. When using the BlueKitchen stack in the central role, it does not support a remote peripheral initiating the MTU exchange. NimBLE works for both roles.

## L2CAP connection-oriented-channels

> This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer).

> Note: This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening).

> Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID).

> Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in `l2cap_recvinto`.

BLE.l2cap_listen(psm, mtu, /)

  Start listening for incoming L2CAP channel requests on the specified psm with the local MTU set to mtu.

  When a remote device initiates a connection, the `_IRQ_L2CAP_ACCEPT` event will be raised, which gives the listening server a chance to reject the incoming connection (by returning a non-zero integer).

  Once the connection is accepted, the `_IRQ_L2CAP_CONNECT` event will be raised, allowing the server to obtain the channel id (CID) and the local and remote MTU.

  Note: It is not currently possible to stop listening.

BLE.l2cap_connect(conn_handle, psm, mtu, /)

  Connect to a listening peer on the specified psm with local MTU set to mtu.

  On successful connection, the the `_IRQ_L2CAP_CONNECT` event will be raised, allowing the client to obtain the CID and the local and remote (peer) MTU.

  An unsuccessful connection will raise the `_IRQ_L2CAP_DISCONNECT` event with a non-zero status.

BLE.l2cap_disconnect(conn_handle, cid, /)

  Disconnect an active L2CAP channel with the specified conn_handle and cid.

BLE.l2cap_send(conn_handle, cid, buf, /)

  Send the specified buf (which must support the buffer protocol) on the L2CAP channel identified by conn_handle and cid.

  The specified buffer cannot be larger than the remote (peer) MTU, and no more than twice the size of the local MTU.

  This will return `False` if the channel is now “stalled”, which means that `l2cap_send` must not be called again until the `_IRQ_L2CAP_SEND_READY` event is received (which will happen when the remote device grants more credits, typically after it has received and processed the data).

BLE.l2cap_recvinto(conn_handle, cid, buf, /)

  Receive data from the specified conn_handle and cid into the provided buf (which must support the buffer protocol, e.g. bytearray or memoryview).

  Returns the number of bytes read from the channel.

  If buf is None, then returns the number of bytes available.

  Note: After receiving the `_IRQ_L2CAP_RECV` event, the application should continue calling `l2cap_recvinto` until no more bytes are available in the receive buffer (typically up to the size of the remote (peer) MTU).

  Until the receive buffer is empty, the remote device will not be granted more channel credits and will be unable to send any more data.

## Pairing and bonding

> Pairing allows a connection to be encrypted and authenticated via exchange of secrets (with optional MITM protection via passkey authentication).

> Bonding is the process of storing those secrets into non-volatile storage. When bonded, a device is able to resolve a resolvable private address (RPA) from another device based on the stored identity resolving key (IRK). To support bonding, an application must implement the `_IRQ_GET_SECRET` and `_IRQ_SET_SECRET` events.

> Note: This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32).

BLE.gap_pair(conn_handle, /)

  Initiate pairing with the remote device.

  Before calling this, ensure that the `io`, `mitm`, `le_secure`, and `bond` configuration options are set (via `config`).

  On successful pairing, the `_IRQ_ENCRYPTION_UPDATE` event will be raised.

BLE.gap_passkey(conn_handle, action, passkey, /)

  Respond to a `_IRQ_PASSKEY_ACTION` event for the specified conn_handle and action.

  The passkey is a numeric value and will depend on on the action (which will depend on what I/O capability has been set):

  > - When the action is `_PASSKEY_ACTION_INPUT`, then the application should prompt the user to enter the passkey that is shown on the remote device.

  > - When the action is `_PASSKEY_ACTION_DISPLAY`, then the application should generate a random 6-digit passkey and show it to the user.

  > - When the action is `_PASSKEY_ACTION_NUMERIC_COMPARISON`, then the application should show the passkey that was provided in the `_IRQ_PASSKEY_ACTION` event and then respond with either `0` (cancel pairing), or `1` (accept pairing).

## class UUID

## Constructor

class bluetooth.UUID(value, /)

  Creates a UUID instance with the specified value.

  The value can be either:

  - A 16-bit integer. e.g. `0x2908`.

  - A 128-bit UUID string. e.g. `'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'`.

Language and External Links

Language
  English
  中文

External links
  openmv.io
  forums.openmv.io
  github.com/openmv/openmv
  micropython.org
  forum.micropython.org
  github.com/micropython/micropython