bluetooth --- Bluetooth cấp thấp

Mô-đun này cung cấp giao diện cho bộ điều khiển Bluetooth tích hợp. Nó hỗ trợ Bluetooth Low Energy (BLE) trong các vai trò Central, Peripheral, Broadcaster và Observer, cũng như GATT Server và Client và các kênh hướng kết nối L2CAP. Một thiết bị có thể hoạt động đồng thời ở nhiều vai trò. Ghép đôi và liên kết cũng được hỗ trợ.

API này nhằm khớp với giao thức Bluetooth cấp thấp và cung cấp các thành phần cơ bản cho các lớp trừu tượng cấp cao hơn, chẳng hạn như các loại thiết bị cụ thể.

Mẹo

Đối với hầu hết các ứng dụng, hãy ưu tiên sử dụng thư viện cấp cao hơn aioble, cung cấp trình bao bọc dựa trên asyncio xung quanh mô-đun này. Xem aioble --- Async BLE.

class BLE

class bluetooth.BLE

Trả về đối tượng BLE singleton.

Cấu hình

active(active: bool | None = None, /) bool

Tùy chọn thay đổi trạng thái hoạt động của radio BLE và trả về trạng thái hiện tại.

Radio phải được kích hoạt trước khi sử dụng bất kỳ phương thức nào khác trong lớp này.

config(param: str, /) Any
config(*, **kwargs: Any) None

Lấy hoặc đặt các giá trị cấu hình của giao diện BLE. Để lấy một giá trị, tên tham số phải được trích dẫn dưới dạng chuỗi và chỉ một tham số được truy vấn tại một thời điểm. Để đặt các giá trị, hãy sử dụng cú pháp từ khóa, và có thể đặt một hoặc nhiều tham số cùng lúc.

Các giá trị hiện được hỗ trợ là:

  • 'mac': Địa chỉ hiện đang sử dụng, tùy thuộc vào chế độ địa chỉ hiện tại. Trả về một tuple (addr_type, addr).

    Xem gap_scan để biết chi tiết về loại địa chỉ.

    Chỉ có thể truy vấn khi giao diện đang hoạt động.

  • 'addr_mode': Đặt chế độ địa chỉ. Các giá trị là:

    Giá trị

    Tên

    Hành vi

    0x00

    PUBLIC

    Sử dụng địa chỉ công khai của bộ điều khiển.

    0x01

    RANDOM

    Sử dụng địa chỉ tĩnh được tạo ra.

    0x02

    RPA

    Sử dụng địa chỉ riêng tư có thể phân giải.

    0x03

    NRPA

    Sử dụng địa chỉ riêng tư không thể phân giải.

    Theo mặc định, giao diện sẽ sử dụng địa chỉ PUBLIC nếu có, ngược lại sẽ sử dụng địa chỉ RANDOM.

  • 'gap_name': Lấy/đặt tên thiết bị GAP được sử dụng bởi dịch vụ Generic Access (UUID 0x1800), đặc trưng Device Name (UUID 0x2a00). Có thể đặt bất cứ lúc nào và thay đổi nhiều lần.

  • 'rxbuf': Lấy/đặt kích thước tính bằng byte của bộ đệm nội bộ được dùng để lưu trữ các sự kiện đến. Bộ đệm này là toàn cục cho toàn bộ trình điều khiển BLE và xử lý dữ liệu đến cho tất cả các sự kiện, bao gồm tất cả các đặc trưng. Tăng giá trị này cho phép xử lý tốt hơn dữ liệu đến theo từng đợt (ví dụ: kết quả quét) và khả năng nhận các giá trị đặc trưng lớn hơn.

  • 'mtu': Lấy/đặt MTU sẽ được sử dụng trong quá trình trao đổi ATT MTU. MTU kết quả sẽ là giá trị nhỏ nhất giữa giá trị này và MTU của thiết bị từ xa. Trao đổi ATT MTU sẽ không tự động diễn ra (trừ khi thiết bị từ xa khởi tạo), và phải được khởi tạo thủ công bằng gattc_exchange_mtu. Sử dụng sự kiện _IRQ_MTU_EXCHANGED để phát hiện MTU cho một kết nối cụ thể.

  • 'bond': Đặt xem liên kết có được bật trong quá trình ghép đôi hay không. Khi được bật, các yêu cầu ghép đôi sẽ đặt cờ "bond" và các khóa sẽ được cả hai thiết bị lưu trữ.

  • 'mitm': Đặt xem bảo vệ MITM có được yêu cầu cho việc ghép đôi hay không.

  • 'io': Đặt khả năng I/O của thiết bị này.

    Các tùy chọn có sẵn là:

    Hằng số

    Giá trị

    Khả năng

    _IO_CAPABILITY_DISPLAY_ONLY

    0

    Chỉ hiển thị

    _IO_CAPABILITY_DISPLAY_YESNO

    1

    Hiển thị với đầu vào có/không

    _IO_CAPABILITY_KEYBOARD_ONLY

    2

    Chỉ bàn phím

    _IO_CAPABILITY_NO_INPUT_OUTPUT

    3

    Không có đầu vào hoặc đầu ra

    _IO_CAPABILITY_KEYBOARD_DISPLAY

    4

    Bàn phím và màn hình hiển thị

  • 'le_secure': Đặt xem ghép đôi "LE Secure" có được yêu cầu hay không. Mặc định là false (tức là cho phép "Legacy Pairing").

Xử lý sự kiện

irq(handler: Callable[[int, Tuple], Any | None], /) None

Đăng ký hàm gọi lại cho các sự kiện từ BLE stack. handler nhận hai đối số: event (sẽ là một trong các mã bên dưới) và data (là một tuple các giá trị theo từng sự kiện cụ thể).

Lưu ý: Để tối ưu hóa ngăn phân bổ bộ nhớ không cần thiết, các mục addr, adv_data, char_data, notify_datauuid trong các tuple là các thực thể memoryview chỉ đọc trỏ đến ringbuffer nội bộ của bluetooth, và chỉ hợp lệ trong thời gian gọi hàm xử lý IRQ. Nếu chương trình cần lưu một trong các giá trị này để truy cập sau khi hàm xử lý IRQ đã trả về (ví dụ: bằng cách lưu vào một thực thể lớp hoặc biến toàn cục), thì cần tạo bản sao dữ liệu, bằng cách sử dụng bytes() hoặc bluetooth.UUID(), như thế này:

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

Ví dụ, hàm xử lý IRQ cho kết quả quét có thể kiểm tra adv_data để xác định xem đó có phải là thiết bị đúng không, và chỉ khi đó mới sao chép dữ liệu địa chỉ để sử dụng ở nơi khác trong chương trình. Và để in dữ liệu từ bên trong hàm xử lý IRQ, cần dùng print(bytes(addr)).

Một hàm xử lý thường phân nhánh theo mã sự kiện và giải nén tuple tải trọng theo từng sự kiện:

def bt_irq(event, data):
    if event == _IRQ_CENTRAL_CONNECT:
        conn_handle, addr_type, addr = data
        ...
    elif event == _IRQ_SCAN_RESULT:
        addr_type, addr, adv_type, rssi, adv_data = data
        ...

Mọi mã sự kiện, tải trọng mà nó cung cấp và mô tả ngắn gọn đều được liệt kê bên dưới. Đối với các sự kiện có trường status được đề cập, status0 khi thành công và giá trị khác không theo từng triển khai cụ thể khi thất bại.

Hằng số

Giá trị

Sự kiện

Tuple tải trọng

_IRQ_CENTRAL_CONNECT

1

Một central đã kết nối với peripheral này.

(conn_handle, addr_type, addr)

_IRQ_CENTRAL_DISCONNECT

2

Một central đã ngắt kết nối khỏi peripheral này.

(conn_handle, addr_type, addr)

_IRQ_GATTS_WRITE

3

Một client đã kết nối đã ghi vào một đặc trưng hoặc bộ mô tả cục bộ. Sử dụng gatts_read để lấy giá trị mới.

(conn_handle, attr_handle)

_IRQ_GATTS_READ_REQUEST

4

Một client đã kết nối đã phát hành yêu cầu đọc. Trả về mã lỗi khác không từ bảng bên dưới để từ chối đọc, hoặc 0 / None để chấp nhận.

(conn_handle, attr_handle)

_IRQ_SCAN_RESULT

5

Một gói quảng bá duy nhất đã được nhận trong quá trình quét chủ động.

(addr_type, addr, adv_type, rssi, adv_data)

_IRQ_SCAN_DONE

6

Lần quét hiện tại đã kết thúc, hoặc vì thời gian đã cấu hình đã trôi qua hoặc vì gap_scan(None) đã được gọi.

()

_IRQ_PERIPHERAL_CONNECT

7

Một gap_connect đã phát hành trước đó đã thành công.

(conn_handle, addr_type, addr)

_IRQ_PERIPHERAL_DISCONNECT

8

Một peripheral đã kết nối đã ngắt kết nối.

(conn_handle, addr_type, addr)

_IRQ_GATTC_SERVICE_RESULT

9

Một dịch vụ đã được tìm thấy bởi gattc_discover_services.

(conn_handle, start_handle, end_handle, uuid)

_IRQ_GATTC_SERVICE_DONE

10

Khám phá dịch vụ đã hoàn thành.

(conn_handle, status)

_IRQ_GATTC_CHARACTERISTIC_RESULT

11

Một đặc trưng đã được tìm thấy bởi gattc_discover_characteristics.

(conn_handle, end_handle, value_handle, properties, uuid)

_IRQ_GATTC_CHARACTERISTIC_DONE

12

Khám phá đặc trưng đã hoàn thành.

(conn_handle, status)

_IRQ_GATTC_DESCRIPTOR_RESULT

13

Một bộ mô tả đã được tìm thấy bởi gattc_discover_descriptors.

(conn_handle, dsc_handle, uuid)

_IRQ_GATTC_DESCRIPTOR_DONE

14

Khám phá bộ mô tả đã hoàn thành.

(conn_handle, status)

_IRQ_GATTC_READ_RESULT

15

Một gattc_read đã phát hành trước đó đã trả về dữ liệu.

(conn_handle, value_handle, char_data)

_IRQ_GATTC_READ_DONE

16

Một gattc_read đã phát hành trước đó đã hoàn thành.

(conn_handle, value_handle, status)

_IRQ_GATTC_WRITE_DONE

17

Một gattc_write đã phát hành trước đó đã được xác nhận.

(conn_handle, value_handle, status)

_IRQ_GATTC_NOTIFY

18

Một máy chủ từ xa đã gửi thông báo (không được xác nhận).

(conn_handle, value_handle, notify_data)

_IRQ_GATTC_INDICATE

19

Một máy chủ từ xa đã gửi chỉ thị (được xác nhận).

(conn_handle, value_handle, notify_data)

_IRQ_GATTS_INDICATE_DONE

20

Một chỉ thị đã gửi trước đó đã được client xác nhận (hoặc đã hết thời gian chờ).

(conn_handle, value_handle, status)

_IRQ_MTU_EXCHANGED

21

Trao đổi ATT MTU đã hoàn thành (được khởi tạo bởi một trong hai bên).

(conn_handle, mtu)

_IRQ_L2CAP_ACCEPT

22

Một thiết bị từ xa đã yêu cầu kết nối L2CAP trên PSM mà thiết bị này đang lắng nghe. Trả về số nguyên khác không để từ chối, hoặc 0 / None để chấp nhận.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_CONNECT

23

Một kênh L2CAP hiện đã được thiết lập, bằng cách chấp nhận yêu cầu đến hoặc bằng cách hoàn thành l2cap_connect đi.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_DISCONNECT

24

Một kênh L2CAP đã bị ngắt kết nối. status0 cho ngắt kết nối sạch, hoặc khác không nếu một lần thử kết nối đi thất bại.

(conn_handle, cid, psm, status)

_IRQ_L2CAP_RECV

25

Dữ liệu đã đến trên một kênh L2CAP. Gọi l2cap_recvinto để đọc.

(conn_handle, cid)

_IRQ_L2CAP_SEND_READY

26

Một l2cap_send trước đó đã trả về False đã được xả và kênh đã sẵn sàng trở lại. status khác không có nghĩa là bộ đệm truyền đã tràn và ứng dụng phải gửi lại dữ liệu.

(conn_handle, cid, status)

_IRQ_CONNECTION_UPDATE

27

Thiết bị từ xa đã cập nhật các tham số kết nối (khoảng thời gian, độ trễ, thời gian chờ giám sát).

(conn_handle, conn_interval, conn_latency, supervision_timeout, status)

_IRQ_ENCRYPTION_UPDATE

28

Trạng thái mã hóa của kết nối đã thay đổi, thường là sau khi ghép đôi hoặc liên kết hoàn thành.

(conn_handle, encrypted, authenticated, bonded, key_size)

_IRQ_GET_SECRET

29

Stack đang yêu cầu một bí mật liên kết đã lưu. Nếu keyNone, trả về giá trị thứ index đã lưu của sec_type; ngược lại trả về giá trị liên quan đến (sec_type, key) đã cho. Trả về None nếu không có gì được lưu trữ.

(sec_type, index, key)

_IRQ_SET_SECRET

30

Stack đang yêu cầu ứng dụng lưu trữ một bí mật liên kết. Trả về True sau khi đã lưu.

(sec_type, key, value)

_IRQ_PASSKEY_ACTION

31

Một hành động passkey được yêu cầu như một phần của ghép đôi. Phản hồi bằng cách sử dụng gap_passkey; xem bảng passkey-action bên dưới để biết các hành động có thể.

(conn_handle, action, passkey)

Đối với sự kiện _IRQ_GATTS_READ_REQUEST, các mã trả về có sẵn là:

Hằng số

Giá trị

Ý nghĩa

_GATTS_NO_ERROR

0x00

Chấp nhận yêu cầu đọc.

_GATTS_ERROR_READ_NOT_PERMITTED

0x02

Không được phép đọc.

_GATTS_ERROR_WRITE_NOT_PERMITTED

0x03

Không được phép ghi.

_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION

0x05

Client chưa xác thực.

_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION

0x08

Client không được ủy quyền.

_GATTS_ERROR_INSUFFICIENT_ENCRYPTION

0x0f

Liên kết không được mã hóa.

Đối với sự kiện _IRQ_PASSKEY_ACTION, các hành động có sẵn là:

Hằng số

Giá trị

Ý nghĩa

_PASSKEY_ACTION_NONE

0

Không cần hành động.

_PASSKEY_ACTION_INPUT

2

Nhắc người dùng nhập passkey được hiển thị trên thiết bị từ xa.

_PASSKEY_ACTION_DISPLAY

3

Hiển thị passkey 6 chữ số để thiết bị từ xa nhập.

_PASSKEY_ACTION_NUMERIC_COMPARISON

4

Xác nhận rằng passkey khớp với passkey được hiển thị trên thiết bị từ xa.

Để tiết kiệm không gian trong firmware, các hằng số này không được đưa vào mô-đun bluetooth. Thêm những hằng số cần thiết từ danh sách trên vào chương trình của bạn.

Vai trò Broadcaster (Advertiser)

gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None

Bắt đầu quảng bá ở khoảng thời gian được chỉ định (tính bằng micro giây). Khoảng thời gian này sẽ được làm tròn xuống tới 625us gần nhất. Để dừng quảng bá, đặt interval_us thành None.

adv_dataresp_data có thể là bất kỳ kiểu nào triển khai giao thức bộ đệm (ví dụ: bytes, bytearray, str). adv_data được đưa vào tất cả các lần phát quảng bá, và resp_data được gửi để trả lời một lần quét chủ động.

Lưu ý: nếu adv_data (hoặc resp_data) là None, thì dữ liệu được truyền trong lần gọi trước đó tới gap_advertise sẽ được tái sử dụng. Điều này cho phép broadcaster tiếp tục quảng bá chỉ với gap_advertise(interval_us). Để xóa tải trọng quảng bá, hãy truyền bytes rỗng, tức là b''.

Vai trò Observer (Scanner)

gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None

Chạy thao tác quét kéo dài trong thời gian được chỉ định (tính bằng mili giây).

Để quét vô thời hạn, đặt duration_ms thành 0.

Để dừng quét, đặt duration_ms thành None.

Sử dụng interval_uswindow_us để tùy chọn cấu hình chu kỳ làm việc. Scanner sẽ chạy trong window_us micro giây mỗi interval_us micro giây trong tổng cộng duration_ms mili giây. Khoảng thời gian và cửa sổ mặc định lần lượt là 1,28 giây và 11,25 mili giây (quét nền).

Đối với mỗi kết quả quét, sự kiện _IRQ_SCAN_RESULT sẽ được kích hoạt, với dữ liệu sự kiện (addr_type, addr, adv_type, rssi, adv_data).

Các giá trị addr_type cho biết địa chỉ công khai hoặc ngẫu nhiên:

Giá trị

Tên

Ý nghĩa

0x00

PUBLIC

Địa chỉ thiết bị công khai.

0x01

RANDOM

Địa chỉ ngẫu nhiên (tĩnh, RPA hoặc NRPA; loại được mã hóa trong chính địa chỉ).

Các giá trị adv_type tương ứng với Bluetooth Specification:

Giá trị

Tên

Ý nghĩa

0x00

ADV_IND

Quảng bá không hướng có thể kết nối và quét.

0x01

ADV_DIRECT_IND

Quảng bá có hướng có thể kết nối.

0x02

ADV_SCAN_IND

Quảng bá không hướng có thể quét.

0x03

ADV_NONCONN_IND

Quảng bá không hướng không thể kết nối.

0x04

SCAN_RSP

Phản hồi quét.

active có thể được đặt True nếu bạn muốn nhận phản hồi quét trong kết quả.

Khi quét dừng lại (do thời gian kết thúc hoặc bị dừng rõ ràng), sự kiện _IRQ_SCAN_DONE sẽ được kích hoạt.

Vai trò Central

Thiết bị central có thể kết nối với các peripheral mà nó đã phát hiện bằng vai trò observer (xem gap_scan) hoặc với địa chỉ đã biết.

gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None

Kết nối với một peripheral.

Xem gap_scan để biết chi tiết về các loại địa chỉ.

Để hủy sớm một lần thử kết nối đang chờ, hãy gọi gap_connect(None).

Khi thành công, sự kiện _IRQ_PERIPHERAL_CONNECT sẽ được kích hoạt. Nếu hủy lần thử kết nối, sự kiện _IRQ_PERIPHERAL_DISCONNECT sẽ được kích hoạt.

Thiết bị sẽ chờ tối đa scan_duration_ms để nhận tải trọng quảng bá từ thiết bị.

Khoảng thời gian kết nối có thể được cấu hình tính bằng micro giây bằng cách sử dụng min_conn_interval_us và/hoặc max_conn_interval_us. Ngược lại, một khoảng thời gian mặc định sẽ được chọn, thường từ 30000 đến 50000 micro giây. Khoảng thời gian ngắn hơn sẽ tăng thông lượng, nhưng tốn nhiều điện năng hơn.

Vai trò Peripheral

Thiết bị peripheral dự kiến gửi các quảng bá có thể kết nối (xem gap_advertise). Thường sẽ hoạt động như GATT server, sau khi đã đăng ký các dịch vụ và đặc trưng bằng gatts_register_services.

Khi central kết nối, sự kiện _IRQ_CENTRAL_CONNECT sẽ được kích hoạt.

Vai trò Central & Peripheral

gap_disconnect(conn_handle: int, /) bool

Ngắt kết nối tay cầm kết nối được chỉ định. Đây có thể là central đã kết nối với thiết bị này (nếu đang hoạt động như peripheral) hoặc peripheral đã được kết nối trước đó bởi thiết bị này (nếu đang hoạt động như central).

Khi thành công, sự kiện _IRQ_PERIPHERAL_DISCONNECT hoặc _IRQ_CENTRAL_DISCONNECT sẽ được kích hoạt.

Trả về False nếu tay cầm kết nối không được kết nối, và True nếu không.

GATT Server

Một GATT server có một tập hợp các dịch vụ đã đăng ký. Mỗi dịch vụ có thể chứa các đặc trưng, mỗi đặc trưng có một giá trị. Các đặc trưng cũng có thể chứa các bộ mô tả, bản thân chúng có các giá trị.

Các giá trị này được lưu trữ cục bộ, và được truy cập bằng "value handle" được tạo ra trong quá trình đăng ký dịch vụ. Chúng cũng có thể được đọc hoặc ghi bởi một thiết bị client từ xa. Ngoài ra, server có thể "thông báo" một đặc trưng đến client đã kết nối qua tay cầm kết nối.

Thiết bị trong vai trò central hoặc peripheral đều có thể hoạt động như GATT server, tuy nhiên trong hầu hết các trường hợp, thiết bị peripheral thường là server hơn.

Các đặc trưng và bộ mô tả có kích thước tối đa mặc định là 20 byte (ATT MTU mặc định là 23 byte trừ đi 3-byte ATT header; MTU đã đàm phán lớn hơn không tự động nâng giới hạn này). Bất cứ điều gì được ghi vào chúng bởi client sẽ bị cắt ngắn đến độ dài này. Tuy nhiên, bất kỳ lần ghi cục bộ nào đều sẽ tăng kích thước tối đa, vì vậy nếu bạn muốn cho phép các lần ghi lớn hơn từ client đến một đặc trưng nhất định, hãy sử dụng gatts_write sau khi đăng ký. Ví dụ: gatts_write(char_handle, bytes(100)).

gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]

Cấu hình server với các dịch vụ được chỉ định, thay thế bất kỳ dịch vụ nào hiện có.

services_definition là một danh sách các dịch vụ, trong đó mỗi dịch vụ là một tuple hai phần tử chứa UUID và một danh sách các đặc trưng.

Mỗi đặc trưng là một tuple hai hoặc ba phần tử chứa UUID, giá trị flags và tùy chọn danh sách bộ mô tả.

Mỗi bộ mô tả là một tuple hai phần tử chứa UUID và giá trị flags.

flags là sự kết hợp bitwise-OR của các cờ được định nghĩa bên dưới. Chúng đặt cả hành vi của đặc trưng (hoặc bộ mô tả) cũng như các yêu cầu bảo mật và quyền riêng tư.

Giá trị trả về là một danh sách (một phần tử cho mỗi dịch vụ) các tuple (mỗi phần tử là value handle). Các handle đặc trưng và bộ mô tả được làm phẳng vào cùng một tuple, theo thứ tự chúng được định nghĩa.

Ví dụ sau đây đăng ký hai dịch vụ (Heart Rate và Nordic UART):

bt = bluetooth.BLE()
bt.active(True)

# Heart Rate service: one Heart Rate Measurement characteristic.
HR_SERVICE = (
    bluetooth.UUID(0x180D),
    (
        (bluetooth.UUID(0x2A37),
         bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY),
    ),
)

# Nordic UART service: a TX characteristic the client subscribes
# to for notifications, and an RX characteristic it writes to.
UART_SERVICE = (
    bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'),
    (
        (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'),
         bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY),
        (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'),
         bluetooth.FLAG_WRITE),
    ),
)

((hr,), (tx, rx)) = bt.gatts_register_services(
    (HR_SERVICE, UART_SERVICE),
)

Ba value handle (hr, tx, rx) có thể được sử dụng với gatts_read, gatts_write, gatts_notifygatts_indicate.

Lưu ý: Phải dừng quảng bá trước khi đăng ký dịch vụ.

Các cờ có sẵn cho đặc trưng và bộ mô tả là:

Hằng số

Giá trị

Ý nghĩa

_FLAG_BROADCAST

0x0001

Đặc trưng có thể được phát quảng bá.

_FLAG_READ

0x0002

Client có thể đọc giá trị.

_FLAG_WRITE_NO_RESPONSE

0x0004

Client có thể ghi mà không cần phản hồi.

_FLAG_WRITE

0x0008

Client có thể ghi với phản hồi được xác nhận.

_FLAG_NOTIFY

0x0010

Server có thể gửi thông báo (không được xác nhận).

_FLAG_INDICATE

0x0020

Server có thể gửi chỉ thị (được xác nhận).

_FLAG_AUTHENTICATED_SIGNED_WRITE

0x0040

Client có thể phát hành ghi có ký xác thực.

_FLAG_AUX_WRITE

0x0100

Thuộc tính mở rộng: cho phép ghi xếp hàng/đáng tin cậy.

_FLAG_READ_ENCRYPTED

0x0200

Đọc yêu cầu liên kết được mã hóa.

_FLAG_READ_AUTHENTICATED

0x0400

Đọc yêu cầu liên kết đã xác thực (được bảo vệ MITM).

_FLAG_READ_AUTHORIZED

0x0800

Đọc yêu cầu ủy quyền cấp ứng dụng.

_FLAG_WRITE_ENCRYPTED

0x1000

Ghi yêu cầu liên kết được mã hóa.

_FLAG_WRITE_AUTHENTICATED

0x2000

Ghi yêu cầu liên kết đã xác thực (được bảo vệ MITM).

_FLAG_WRITE_AUTHORIZED

0x4000

Ghi yêu cầu ủy quyền cấp ứng dụng.

Giống như các hằng số sự kiện ở trên, các cờ này không được cung cấp bởi mô-đun bluetooth; hãy sao chép những cờ bạn cần vào chương trình của bạn.

gatts_read(value_handle: int, /) bytes

Đọc giá trị cục bộ cho handle này (đã được ghi bởi gatts_write hoặc bởi client từ xa).

gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None

Ghi giá trị cục bộ cho handle này, có thể được đọc bởi client.

Nếu send_updateTrue, thì bất kỳ client nào đã đăng ký sẽ được thông báo (hoặc chỉ thị, tùy thuộc vào những gì họ đã đăng ký và các thao tác mà đặc trưng hỗ trợ) về lần ghi này.

gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Gửi yêu cầu thông báo đến client đã kết nối.

Nếu dataNone (mặc định), thì giá trị cục bộ hiện tại (như đã đặt với gatts_write) sẽ được gửi.

Ngược lại, nếu data không phải là None, thì giá trị đó được gửi đến client như một phần của thông báo. Giá trị cục bộ sẽ không bị thay đổi.

Lưu ý: Thông báo sẽ được gửi bất kể trạng thái đăng ký của client đối với đặc trưng này.

gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Gửi yêu cầu chỉ thị đến client đã kết nối.

Nếu dataNone (mặc định), thì giá trị cục bộ hiện tại (như đã đặt với gatts_write) sẽ được gửi.

Ngược lại, nếu data không phải là None, thì giá trị đó được gửi đến client như một phần của chỉ thị. Giá trị cục bộ sẽ không bị thay đổi.

Khi xác nhận (hoặc thất bại, ví dụ: hết thời gian chờ), sự kiện _IRQ_GATTS_INDICATE_DONE sẽ được kích hoạt.

Lưu ý: Chỉ thị sẽ được gửi bất kể trạng thái đăng ký của client đối với đặc trưng này.

gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None

Đặt kích thước bộ đệm nội bộ cho một giá trị tính bằng byte. Điều này sẽ giới hạn kích thước ghi lớn nhất có thể được nhận. Mặc định là 20 byte (ATT MTU mặc định là 23 trừ đi 3-byte ATT header).

Đặt append thành True sẽ làm cho tất cả các lần ghi từ xa thêm vào, thay vì thay thế, giá trị hiện tại. Tối đa len byte có thể được đệm theo cách này. Khi bạn sử dụng gatts_read, giá trị sẽ bị xóa sau khi đọc. Tính năng này hữu ích khi triển khai thứ gì đó như Nordic UART Service.

GATT Client

Một GATT client có thể khám phá và đọc/ghi các đặc trưng trên GATT server từ xa.

Thiết bị vai trò central thường đóng vai trò GATT client hơn, tuy nhiên peripheral cũng có thể đóng vai trò client để khám phá thông tin về central đã kết nối với nó (ví dụ: đọc tên thiết bị từ dịch vụ thông tin thiết bị).

gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None

Truy vấn server đã kết nối về các dịch vụ của nó.

Tùy chọn chỉ định uuid dịch vụ để chỉ truy vấn dịch vụ đó.

Đối với mỗi dịch vụ được phát hiện, sự kiện _IRQ_GATTC_SERVICE_RESULT sẽ được kích hoạt, tiếp theo là _IRQ_GATTC_SERVICE_DONE khi hoàn thành.

gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None

Truy vấn server đã kết nối về các đặc trưng trong phạm vi được chỉ định.

Tùy chọn chỉ định uuid đặc trưng để chỉ truy vấn đặc trưng đó.

Truyền start_handle=1end_handle=0xffff bao phủ toàn bộ phạm vi attribute-handle GATT, vì vậy sự kết hợp này thực sự tìm kiếm mọi dịch vụ trên thiết bị từ xa.

Đối với mỗi đặc trưng được phát hiện, sự kiện _IRQ_GATTC_CHARACTERISTIC_RESULT sẽ được kích hoạt, tiếp theo là _IRQ_GATTC_CHARACTERISTIC_DONE khi hoàn thành.

gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None

Truy vấn server đã kết nối về các bộ mô tả trong phạm vi được chỉ định.

Đối với mỗi bộ mô tả được phát hiện, sự kiện _IRQ_GATTC_DESCRIPTOR_RESULT sẽ được kích hoạt, tiếp theo là _IRQ_GATTC_DESCRIPTOR_DONE khi hoàn thành.

gattc_read(conn_handle: int, value_handle: int, /) None

Phát hành lệnh đọc từ xa đến server đã kết nối cho handle đặc trưng hoặc bộ mô tả được chỉ định.

Khi có giá trị, sự kiện _IRQ_GATTC_READ_RESULT sẽ được kích hoạt, tiếp theo là _IRQ_GATTC_READ_DONE khi hoàn thành.

gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None

Phát hành lệnh ghi từ xa đến server đã kết nối cho handle đặc trưng hoặc bộ mô tả được chỉ định.

Đối số mode chỉ định hành vi ghi, với các giá trị hiện được hỗ trợ là:

  • mode=0 (mặc định) là ghi không có phản hồi: lệnh ghi sẽ được gửi đến server từ xa nhưng không có xác nhận nào được trả về, và không có sự kiện nào được kích hoạt.

  • mode=1 là ghi có phản hồi: server từ xa được yêu cầu gửi phản hồi/xác nhận rằng nó đã nhận được dữ liệu.

Nếu nhận được phản hồi từ server từ xa, sự kiện _IRQ_GATTC_WRITE_DONE sẽ được kích hoạt.

gattc_exchange_mtu(conn_handle: int, /) None

Khởi tạo trao đổi MTU với server đã kết nối, sử dụng MTU ưu tiên được đặt bằng BLE.config(mtu=value).

Sự kiện _IRQ_MTU_EXCHANGED sẽ được kích hoạt khi trao đổi MTU hoàn thành.

Trao đổi MTU thường được khởi tạo bởi central; NimBLE hỗ trợ cả hai vai trò.

Kênh hướng kết nối L2CAP

Tính năng này cho phép trao đổi dữ liệu dạng socket giữa hai thiết bị BLE. Khi các thiết bị đã kết nối qua GAP, một trong hai thiết bị có thể lắng nghe thiết bị kia kết nối trên PSM (Protocol/Service Multiplexer) dạng số.

Chỉ có thể có một kênh L2CAP hoạt động tại một thời điểm (tức là không thể kết nối trong khi đang lắng nghe).

Các kênh L2CAP đang hoạt động được xác định bởi tay cầm kết nối mà chúng được thiết lập và CID (channel ID).

Các kênh hướng kết nối có kiểm soát luồng dựa trên tín dụng tích hợp. Không giống như ATT, nơi các thiết bị đàm phán MTU chia sẻ, cả thiết bị lắng nghe và kết nối đều đặt MTU độc lập riêng, giới hạn lượng dữ liệu tối đa đang chờ xử lý mà thiết bị từ xa có thể gửi trước khi được tiêu thụ hoàn toàn trong l2cap_recvinto.

l2cap_listen(psm: int, mtu: int, /) None

Bắt đầu lắng nghe các yêu cầu kênh L2CAP đến trên psm được chỉ định với MTU cục bộ được đặt thành mtu.

Khi thiết bị từ xa khởi tạo kết nối, sự kiện _IRQ_L2CAP_ACCEPT sẽ được kích hoạt, cho phép server lắng nghe có cơ hội từ chối kết nối đến (bằng cách trả về số nguyên khác không).

Sau khi kết nối được chấp nhận, sự kiện _IRQ_L2CAP_CONNECT sẽ được kích hoạt, cho phép server lấy CID và MTU cục bộ và từ xa.

Lưu ý: Hiện tại không thể dừng lắng nghe.

l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None

Kết nối đến peer đang lắng nghe trên psm được chỉ định với MTU cục bộ được đặt thành mtu.

Khi kết nối thành công, sự kiện _IRQ_L2CAP_CONNECT sẽ được kích hoạt, cho phép client lấy CID và MTU cục bộ và từ xa (peer).

Kết nối không thành công sẽ kích hoạt sự kiện _IRQ_L2CAP_DISCONNECT với trạng thái khác không.

l2cap_disconnect(conn_handle: int, cid: int, /) None

Ngắt kết nối kênh L2CAP đang hoạt động với conn_handlecid được chỉ định.

l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool

Gửi buf được chỉ định (phải hỗ trợ giao thức bộ đệm) trên kênh L2CAP được xác định bởi conn_handlecid.

Bộ đệm phải thỏa mãn cả hai giới hạn: không được vượt quá MTU từ xa (peer) và không được vượt quá hai lần MTU cục bộ.

Điều này sẽ trả về False nếu kênh hiện đang "bị trì hoãn", có nghĩa là l2cap_send không được gọi lại cho đến khi nhận được sự kiện _IRQ_L2CAP_SEND_READY (điều này sẽ xảy ra khi thiết bị từ xa cấp thêm tín dụng, thường là sau khi nhận và xử lý dữ liệu).

l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int

Nhận dữ liệu từ conn_handlecid được chỉ định vào buf được cung cấp (phải hỗ trợ giao thức bộ đệm, ví dụ: bytearray hoặc memoryview).

Trả về số byte đọc từ kênh.

Nếu bufNone, thì trả về số byte có sẵn.

Lưu ý: Sau khi nhận sự kiện _IRQ_L2CAP_RECV, ứng dụng nên tiếp tục gọi l2cap_recvinto cho đến khi không còn byte nào trong bộ đệm nhận (thường là tối đa kích thước MTU của thiết bị từ xa (peer)).

Cho đến khi bộ đệm nhận trống, thiết bị từ xa sẽ không được cấp thêm tín dụng kênh và sẽ không thể gửi thêm dữ liệu.

Ghép đôi và liên kết

Ghép đôi cho phép kết nối được mã hóa và xác thực thông qua trao đổi bí mật (với bảo vệ MITM tùy chọn thông qua xác thực passkey).

Liên kết là quá trình lưu trữ các bí mật đó vào bộ nhớ không bay hơi. Khi đã liên kết, thiết bị có thể phân giải địa chỉ riêng tư có thể phân giải (RPA) từ thiết bị khác dựa trên khóa phân giải danh tính đã lưu trữ (IRK). Để hỗ trợ liên kết, ứng dụng phải triển khai các sự kiện _IRQ_GET_SECRET_IRQ_SET_SECRET.

gap_pair(conn_handle: int, /) None

Khởi tạo ghép đôi với thiết bị từ xa.

Trước khi gọi hàm này, hãy đảm bảo rằng các tùy chọn cấu hình io, mitm, le_securebond đã được đặt (qua config).

Khi ghép đôi thành công, sự kiện _IRQ_ENCRYPTION_UPDATE sẽ được kích hoạt.

gap_passkey(conn_handle: int, action: int, passkey: int, /) None

Phản hồi sự kiện _IRQ_PASSKEY_ACTION cho conn_handleaction được chỉ định. Ý nghĩa của passkey phụ thuộc vào action (lần lượt phụ thuộc vào khả năng I/O đã cấu hình):

Hành động

Phản hồi passkey yêu cầu

_PASSKEY_ACTION_INPUT

Passkey mà người dùng đọc từ thiết bị từ xa.

_PASSKEY_ACTION_DISPLAY

Passkey ngẫu nhiên 6 chữ số được tạo cục bộ hiển thị cho người dùng.

_PASSKEY_ACTION_NUMERIC_COMPARISON

1 để chấp nhận passkey được hiển thị trong sự kiện _IRQ_PASSKEY_ACTION, hoặc 0 để hủy ghép đôi.

class UUID

class bluetooth.UUID(value: int | bytes | str, /)

Tạo một thực thể UUID với value được chỉ định. Bluetooth sử dụng ba độ rộng UUID; UUID chấp nhận bất kỳ trong số chúng:

Độ rộng UUID

Các kiểu value được chấp nhận

Ví dụ

16-bit

int hoặc bộ đệm 2 byte (little-endian)

UUID(0x2908) hoặc UUID(b'\x08\x29')

32-bit

Bộ đệm 4 byte (little-endian)

UUID(b'\x08\x29\x00\x00')

128-bit

Bộ đệm 16 byte hoặc chuỗi có dấu gạch ngang

UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')

UUID 16-bit và 32-bit thường là các định danh được SIG phân bổ (xem Bluetooth assigned numbers); UUID 128-bit thường được định nghĩa bởi nhà cung cấp.