bumble 0.0.170__tar.gz → 0.0.172__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bumble-0.0.170 → bumble-0.0.172}/.github/workflows/python-build-test.yml +2 -0
- {bumble-0.0.170 → bumble-0.0.172}/.vscode/settings.json +2 -0
- {bumble-0.0.170 → bumble-0.0.172}/PKG-INFO +2 -1
- {bumble-0.0.170 → bumble-0.0.172}/apps/console.py +1 -1
- {bumble-0.0.170 → bumble-0.0.172}/apps/controller_info.py +2 -1
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/speaker.py +2 -2
- bumble-0.0.172/bumble/_version.py +8 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/att.py +77 -51
- {bumble-0.0.170 → bumble-0.0.172}/bumble/device.py +5 -3
- {bumble-0.0.170 → bumble-0.0.172}/bumble/gatt.py +22 -20
- {bumble-0.0.170 → bumble-0.0.172}/bumble/gatt_client.py +67 -32
- {bumble-0.0.170 → bumble-0.0.172}/bumble/gatt_server.py +75 -31
- {bumble-0.0.170 → bumble-0.0.172}/bumble/l2cap.py +92 -125
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/security.py +5 -1
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/android_emulator.py +7 -4
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/android_netsim.py +84 -50
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/common.py +3 -8
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/ws_client.py +9 -7
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/PKG-INFO +2 -1
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/SOURCES.txt +1 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/requires.txt +3 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/Cargo.lock +159 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/Cargo.toml +11 -2
- {bumble-0.0.170 → bumble-0.0.172}/rust/README.md +1 -1
- {bumble-0.0.170 → bumble-0.0.172}/rust/pytests/assigned_numbers.rs +14 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/adv.rs +14 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/logging.rs +14 -0
- bumble-0.0.172/rust/tools/file_header.rs +78 -0
- {bumble-0.0.170 → bumble-0.0.172}/setup.cfg +1 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/gatt_test.py +4 -4
- {bumble-0.0.170 → bumble-0.0.172}/web/bumble.js +0 -1
- {bumble-0.0.170 → bumble-0.0.172}/web/scanner/scanner.py +1 -1
- {bumble-0.0.170 → bumble-0.0.172}/web/speaker/speaker.py +1 -1
- bumble-0.0.170/bumble/_version.py +0 -4
- {bumble-0.0.170 → bumble-0.0.172}/.git-blame-ignore-revs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/.github/workflows/code-check.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/.github/workflows/codeql-analysis.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/.github/workflows/python-publish.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/.gitignore +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/CONTRIBUTING.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/LICENSE +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/bench.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/controllers.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/gatt_dump.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/gg_bridge.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/hci_bridge.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/l2cap_bridge.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/link_relay/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/link_relay/link_relay.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/link_relay/logging.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/pair.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/pandora_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/scan.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/show.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/logo.svg +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/speaker.css +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/speaker.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/speaker/speaker.js +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/unbond.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/apps/usb_probe.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/a2dp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/at.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/avdtp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/bridge.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/codecs.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/colors.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/company_ids.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/controller.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/core.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/crypto.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/decoder.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/drivers/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/drivers/rtk.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/gap.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/hci.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/helpers.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/hfp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/host.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/keys.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/link.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pairing.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/config.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/device.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/host.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/py.typed +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/pandora/utils.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/asha_service.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/battery_service.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/device_information_service.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/heart_rate_service.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/profiles/py.typed +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/py.typed +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/rfcomm.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/sdp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/smp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/snoop.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/file.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/common_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/common_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/common_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/hci_packet_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/hci_packet_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/hci_packet_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/packet_streamer_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/packet_streamer_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/startup_pb2.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/startup_pb2.pyi +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/grpc_protobuf/startup_pb2_grpc.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/hci_socket.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/pty.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/py.typed +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/pyusb.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/serial.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/tcp_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/tcp_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/udp.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/usb.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/vhci.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/transport/ws_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/utils.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/vendor/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/vendor/android/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/vendor/android/hci.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/vendor/zephyr/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble/vendor/zephyr/hci.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/dependency_links.txt +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/entry_points.txt +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/bumble.egg-info/top_level.txt +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.svg +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.vectornator/Artboard0.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.vectornator/Document.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.vectornator/Manifest.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.vectornator/Thumbnail.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo.vectornator/UndoHistory.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.svg +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.vectornator/Artboard0.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.vectornator/Document.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.vectornator/Manifest.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.vectornator/Thumbnail.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/images/logo_framed.vectornator/UndoHistory.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/mkdocs.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/requirements.txt +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/api/examples.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/api/guide.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/api/reference.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/bench.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/console.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/gatt_dump.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/gg_bridge.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/hci_bridge.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/link_relay.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/pair.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/show.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/speaker.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/unbond.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/apps_and_tools/usb_probe.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/components/controller.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/components/gatt.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/components/host.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/components/security_manager.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/development/code_style.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/development/contributing.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/development/python_environments.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/downloads/zephyr/hci_usb.zip +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/drivers/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/drivers/realtek.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/examples/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/getting_started.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/hardware/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/bumble_layers.svg +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/console_screenshot.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/favicon.ico +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/logo.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/logo_framed.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/images/speaker_screenshot.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/android.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/linux.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/macos.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/windows.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/winusb_driver.png +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/platforms/zephyr.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/android_emulator.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/file.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/hci_socket.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/pty.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/serial.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/tcp_client.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/tcp_server.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/udp.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/usb.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/vhci.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/ws_client.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/transports/ws_server.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/index.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_1.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_2.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_3.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_4.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_5.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/src/use_cases/use_case_6.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/docs/mkdocs/theme/partials/footer.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/environment.yml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/a2dp_sink1.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/asha_sink1.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/asha_sink2.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/async_runner.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/battery_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/battery_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/classic1.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/classic2.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/device1.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/device2.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/device3.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/device_information_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/device_information_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/heart_rate_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/heart_rate_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/hfp_gateway.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/hfp_handsfree.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/hfp_handsfree.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/keyboard.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/keyboard.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/keyboard.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_a2dp_info.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_a2dp_sink.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_a2dp_source.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_advertiser.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_asha_sink.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_classic_connect.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_classic_discoverable.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_classic_discovery.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_connect_and_encrypt.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_controller.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_controller_with_scanner.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_device_with_snooper.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_gatt_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_gatt_client_and_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_gatt_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_hfp_gateway.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_hfp_handsfree.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_notifier.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_rfcomm_client.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_rfcomm_server.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/run_scanner.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/examples/speaker.json +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/noxfile.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/pyproject.toml +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/.gitignore +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/CHANGELOG.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/examples/battery_client.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/examples/broadcast.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/examples/scanner.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/pytests/pytests.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/pytests/wrapper.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/resources/test/firmware/realtek/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/resources/test/firmware/realtek/rtl8723b_fw_structure.bin +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/resources/test/firmware/realtek/rtl8761bu_fw_structure.bin +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/firmware/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/firmware/rtk.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/l2cap/client_bridge.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/l2cap/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/l2cap/server_bridge.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/cli/usb/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/internal/drivers/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/internal/drivers/rtk.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/internal/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/lib.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/main.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/assigned_numbers/company_ids.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/assigned_numbers/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/assigned_numbers/services.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/core.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/device.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/drivers/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/drivers/rtk.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/gatt_client.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/hci.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/host.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/l2cap.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/mod.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/profile.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/src/wrapper/transport.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/rust/tools/gen_assigned_numbers.rs +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/scripts/process_android_emulator_protos.sh +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/scripts/process_android_netsim_protos.sh +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/setup.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tasks.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/a2dp_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/at_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/avdtp_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/codecs_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/core_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/decoder_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/device_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/g722_sample.g722 +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/hci_data_001.bin +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/hci_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/hfp_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/import_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/keystore_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/l2cap_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/pytest.ini +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/rfcomm_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/sdp_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/self_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/smp_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/test_utils.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/transport_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tests/utils_test.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tools/__init__.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tools/generate_company_id_list.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tools/rtk_fw_download.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/tools/rtk_util.py +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/README.md +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/scanner/scanner.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/speaker/logo.svg +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/speaker/speaker.css +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/speaker/speaker.html +0 -0
- {bumble-0.0.170 → bumble-0.0.172}/web/speaker/speaker.js +0 -0
|
@@ -65,6 +65,8 @@ jobs:
|
|
|
65
65
|
with:
|
|
66
66
|
components: clippy,rustfmt
|
|
67
67
|
toolchain: ${{ matrix.rust-version }}
|
|
68
|
+
- name: Check License Headers
|
|
69
|
+
run: cd rust && cargo run --features dev-tools --bin file-header check-all
|
|
68
70
|
- name: Rust Build
|
|
69
71
|
run: cd rust && cargo build --all-targets && cargo build --all-features --all-targets
|
|
70
72
|
# Lints after build so what clippy needs is already built
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bumble
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.172
|
|
4
4
|
Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
|
|
5
5
|
Home-page: https://github.com/google/bumble
|
|
6
6
|
Author: Google
|
|
@@ -13,6 +13,7 @@ Requires-Dist: appdirs>=1.4; platform_system != "Emscripten"
|
|
|
13
13
|
Requires-Dist: bt-test-interfaces>=0.0.2; platform_system != "Emscripten"
|
|
14
14
|
Requires-Dist: click==8.1.3; platform_system != "Emscripten"
|
|
15
15
|
Requires-Dist: cryptography==39; platform_system != "Emscripten"
|
|
16
|
+
Requires-Dist: cryptography>=39.0; platform_system == "Emscripten"
|
|
16
17
|
Requires-Dist: grpcio==1.57.0; platform_system != "Emscripten"
|
|
17
18
|
Requires-Dist: humanize>=4.6.0; platform_system != "Emscripten"
|
|
18
19
|
Requires-Dist: libusb1>=2.0.1; platform_system != "Emscripten"
|
|
@@ -1172,7 +1172,7 @@ class ScanResult:
|
|
|
1172
1172
|
name = ''
|
|
1173
1173
|
|
|
1174
1174
|
# Remove any '/P' qualifier suffix from the address string
|
|
1175
|
-
address_str =
|
|
1175
|
+
address_str = self.address.to_string(with_type_qualifier=False)
|
|
1176
1176
|
|
|
1177
1177
|
# RSSI bar
|
|
1178
1178
|
bar_string = rssi_bar(self.rssi)
|
|
@@ -63,7 +63,8 @@ async def get_classic_info(host):
|
|
|
63
63
|
if command_succeeded(response):
|
|
64
64
|
print()
|
|
65
65
|
print(
|
|
66
|
-
color('Classic Address:', 'yellow'),
|
|
66
|
+
color('Classic Address:', 'yellow'),
|
|
67
|
+
response.return_parameters.bd_addr.to_string(False),
|
|
67
68
|
)
|
|
68
69
|
|
|
69
70
|
if host.supports_command(HCI_READ_LOCAL_NAME_COMMAND):
|
|
@@ -195,7 +195,7 @@ class WebSocketOutput(QueuedOutput):
|
|
|
195
195
|
except HCI_StatusError:
|
|
196
196
|
pass
|
|
197
197
|
peer_name = '' if connection.peer_name is None else connection.peer_name
|
|
198
|
-
peer_address =
|
|
198
|
+
peer_address = connection.peer_address.to_string(False)
|
|
199
199
|
await self.send_message(
|
|
200
200
|
'connection',
|
|
201
201
|
peer_address=peer_address,
|
|
@@ -376,7 +376,7 @@ class UiServer:
|
|
|
376
376
|
if connection := self.speaker().connection:
|
|
377
377
|
await self.send_message(
|
|
378
378
|
'connection',
|
|
379
|
-
peer_address=
|
|
379
|
+
peer_address=connection.peer_address.to_string(False),
|
|
380
380
|
peer_name=connection.peer_name,
|
|
381
381
|
)
|
|
382
382
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# file generated by setuptools_scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
TYPE_CHECKING = False
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
|
|
7
|
+
__version__ = version = '0.0.172' # type: str
|
|
8
|
+
__version_tuple__ = version_tuple = (0, 0, 172) # type: Tuple[int | str, ...]
|
|
@@ -23,13 +23,14 @@
|
|
|
23
23
|
# Imports
|
|
24
24
|
# -----------------------------------------------------------------------------
|
|
25
25
|
from __future__ import annotations
|
|
26
|
+
import enum
|
|
26
27
|
import functools
|
|
27
28
|
import struct
|
|
28
29
|
from pyee import EventEmitter
|
|
29
|
-
from typing import Dict, Type, TYPE_CHECKING
|
|
30
|
+
from typing import Dict, Type, List, Protocol, Union, Optional, Any, TYPE_CHECKING
|
|
30
31
|
|
|
31
|
-
from bumble.core import UUID, name_or_number,
|
|
32
|
-
from bumble.hci import HCI_Object, key_with_value
|
|
32
|
+
from bumble.core import UUID, name_or_number, ProtocolError
|
|
33
|
+
from bumble.hci import HCI_Object, key_with_value
|
|
33
34
|
from bumble.colors import color
|
|
34
35
|
|
|
35
36
|
if TYPE_CHECKING:
|
|
@@ -182,6 +183,7 @@ UUID_2_FIELD_SPEC = lambda x, y: UUID.parse_uuid_2(x, y) # noqa: E731
|
|
|
182
183
|
# pylint: enable=line-too-long
|
|
183
184
|
# pylint: disable=invalid-name
|
|
184
185
|
|
|
186
|
+
|
|
185
187
|
# -----------------------------------------------------------------------------
|
|
186
188
|
# Exceptions
|
|
187
189
|
# -----------------------------------------------------------------------------
|
|
@@ -209,7 +211,7 @@ class ATT_PDU:
|
|
|
209
211
|
|
|
210
212
|
pdu_classes: Dict[int, Type[ATT_PDU]] = {}
|
|
211
213
|
op_code = 0
|
|
212
|
-
name
|
|
214
|
+
name: str
|
|
213
215
|
|
|
214
216
|
@staticmethod
|
|
215
217
|
def from_bytes(pdu):
|
|
@@ -720,47 +722,67 @@ class ATT_Handle_Value_Confirmation(ATT_PDU):
|
|
|
720
722
|
|
|
721
723
|
|
|
722
724
|
# -----------------------------------------------------------------------------
|
|
723
|
-
class
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
WRITEABLE = 0x02
|
|
727
|
-
READ_REQUIRES_ENCRYPTION = 0x04
|
|
728
|
-
WRITE_REQUIRES_ENCRYPTION = 0x08
|
|
729
|
-
READ_REQUIRES_AUTHENTICATION = 0x10
|
|
730
|
-
WRITE_REQUIRES_AUTHENTICATION = 0x20
|
|
731
|
-
READ_REQUIRES_AUTHORIZATION = 0x40
|
|
732
|
-
WRITE_REQUIRES_AUTHORIZATION = 0x80
|
|
733
|
-
|
|
734
|
-
PERMISSION_NAMES = {
|
|
735
|
-
READABLE: 'READABLE',
|
|
736
|
-
WRITEABLE: 'WRITEABLE',
|
|
737
|
-
READ_REQUIRES_ENCRYPTION: 'READ_REQUIRES_ENCRYPTION',
|
|
738
|
-
WRITE_REQUIRES_ENCRYPTION: 'WRITE_REQUIRES_ENCRYPTION',
|
|
739
|
-
READ_REQUIRES_AUTHENTICATION: 'READ_REQUIRES_AUTHENTICATION',
|
|
740
|
-
WRITE_REQUIRES_AUTHENTICATION: 'WRITE_REQUIRES_AUTHENTICATION',
|
|
741
|
-
READ_REQUIRES_AUTHORIZATION: 'READ_REQUIRES_AUTHORIZATION',
|
|
742
|
-
WRITE_REQUIRES_AUTHORIZATION: 'WRITE_REQUIRES_AUTHORIZATION',
|
|
743
|
-
}
|
|
725
|
+
class ConnectionValue(Protocol):
|
|
726
|
+
def read(self, connection) -> bytes:
|
|
727
|
+
...
|
|
744
728
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
try:
|
|
748
|
-
return functools.reduce(
|
|
749
|
-
lambda x, y: x | get_dict_key_by_value(Attribute.PERMISSION_NAMES, y),
|
|
750
|
-
permissions_str.split(","),
|
|
751
|
-
0,
|
|
752
|
-
)
|
|
753
|
-
except TypeError as exc:
|
|
754
|
-
raise TypeError(
|
|
755
|
-
f"Attribute::permissions error:\nExpected a string containing any of the keys, separated by commas: {','.join(Attribute.PERMISSION_NAMES.values())}\nGot: {permissions_str}"
|
|
756
|
-
) from exc
|
|
729
|
+
def write(self, connection, value: bytes) -> None:
|
|
730
|
+
...
|
|
757
731
|
|
|
758
|
-
|
|
732
|
+
|
|
733
|
+
# -----------------------------------------------------------------------------
|
|
734
|
+
class Attribute(EventEmitter):
|
|
735
|
+
class Permissions(enum.IntFlag):
|
|
736
|
+
READABLE = 0x01
|
|
737
|
+
WRITEABLE = 0x02
|
|
738
|
+
READ_REQUIRES_ENCRYPTION = 0x04
|
|
739
|
+
WRITE_REQUIRES_ENCRYPTION = 0x08
|
|
740
|
+
READ_REQUIRES_AUTHENTICATION = 0x10
|
|
741
|
+
WRITE_REQUIRES_AUTHENTICATION = 0x20
|
|
742
|
+
READ_REQUIRES_AUTHORIZATION = 0x40
|
|
743
|
+
WRITE_REQUIRES_AUTHORIZATION = 0x80
|
|
744
|
+
|
|
745
|
+
@classmethod
|
|
746
|
+
def from_string(cls, permissions_str: str) -> Attribute.Permissions:
|
|
747
|
+
try:
|
|
748
|
+
return functools.reduce(
|
|
749
|
+
lambda x, y: x | Attribute.Permissions[y],
|
|
750
|
+
permissions_str.replace('|', ',').split(","),
|
|
751
|
+
Attribute.Permissions(0),
|
|
752
|
+
)
|
|
753
|
+
except TypeError as exc:
|
|
754
|
+
# The check for `p.name is not None` here is needed because for InFlag
|
|
755
|
+
# enums, the .name property can be None, when the enum value is 0,
|
|
756
|
+
# so the type hint for .name is Optional[str].
|
|
757
|
+
enum_list: List[str] = [p.name for p in cls if p.name is not None]
|
|
758
|
+
enum_list_str = ",".join(enum_list)
|
|
759
|
+
raise TypeError(
|
|
760
|
+
f"Attribute::permissions error:\nExpected a string containing any of the keys, separated by commas: {enum_list_str }\nGot: {permissions_str}"
|
|
761
|
+
) from exc
|
|
762
|
+
|
|
763
|
+
# Permission flags(legacy-use only)
|
|
764
|
+
READABLE = Permissions.READABLE
|
|
765
|
+
WRITEABLE = Permissions.WRITEABLE
|
|
766
|
+
READ_REQUIRES_ENCRYPTION = Permissions.READ_REQUIRES_ENCRYPTION
|
|
767
|
+
WRITE_REQUIRES_ENCRYPTION = Permissions.WRITE_REQUIRES_ENCRYPTION
|
|
768
|
+
READ_REQUIRES_AUTHENTICATION = Permissions.READ_REQUIRES_AUTHENTICATION
|
|
769
|
+
WRITE_REQUIRES_AUTHENTICATION = Permissions.WRITE_REQUIRES_AUTHENTICATION
|
|
770
|
+
READ_REQUIRES_AUTHORIZATION = Permissions.READ_REQUIRES_AUTHORIZATION
|
|
771
|
+
WRITE_REQUIRES_AUTHORIZATION = Permissions.WRITE_REQUIRES_AUTHORIZATION
|
|
772
|
+
|
|
773
|
+
value: Union[str, bytes, ConnectionValue]
|
|
774
|
+
|
|
775
|
+
def __init__(
|
|
776
|
+
self,
|
|
777
|
+
attribute_type: Union[str, bytes, UUID],
|
|
778
|
+
permissions: Union[str, Attribute.Permissions],
|
|
779
|
+
value: Union[str, bytes, ConnectionValue] = b'',
|
|
780
|
+
) -> None:
|
|
759
781
|
EventEmitter.__init__(self)
|
|
760
782
|
self.handle = 0
|
|
761
783
|
self.end_group_handle = 0
|
|
762
784
|
if isinstance(permissions, str):
|
|
763
|
-
self.permissions =
|
|
785
|
+
self.permissions = Attribute.Permissions.from_string(permissions)
|
|
764
786
|
else:
|
|
765
787
|
self.permissions = permissions
|
|
766
788
|
|
|
@@ -778,22 +800,26 @@ class Attribute(EventEmitter):
|
|
|
778
800
|
else:
|
|
779
801
|
self.value = value
|
|
780
802
|
|
|
781
|
-
def encode_value(self, value):
|
|
803
|
+
def encode_value(self, value: Any) -> bytes:
|
|
782
804
|
return value
|
|
783
805
|
|
|
784
|
-
def decode_value(self, value_bytes):
|
|
806
|
+
def decode_value(self, value_bytes: bytes) -> Any:
|
|
785
807
|
return value_bytes
|
|
786
808
|
|
|
787
|
-
def read_value(self, connection: Connection):
|
|
809
|
+
def read_value(self, connection: Optional[Connection]) -> bytes:
|
|
788
810
|
if (
|
|
789
|
-
self.permissions & self.READ_REQUIRES_ENCRYPTION
|
|
790
|
-
|
|
811
|
+
(self.permissions & self.READ_REQUIRES_ENCRYPTION)
|
|
812
|
+
and connection is not None
|
|
813
|
+
and not connection.encryption
|
|
814
|
+
):
|
|
791
815
|
raise ATT_Error(
|
|
792
816
|
error_code=ATT_INSUFFICIENT_ENCRYPTION_ERROR, att_handle=self.handle
|
|
793
817
|
)
|
|
794
818
|
if (
|
|
795
|
-
self.permissions & self.READ_REQUIRES_AUTHENTICATION
|
|
796
|
-
|
|
819
|
+
(self.permissions & self.READ_REQUIRES_AUTHENTICATION)
|
|
820
|
+
and connection is not None
|
|
821
|
+
and not connection.authenticated
|
|
822
|
+
):
|
|
797
823
|
raise ATT_Error(
|
|
798
824
|
error_code=ATT_INSUFFICIENT_AUTHENTICATION_ERROR, att_handle=self.handle
|
|
799
825
|
)
|
|
@@ -803,9 +829,9 @@ class Attribute(EventEmitter):
|
|
|
803
829
|
error_code=ATT_INSUFFICIENT_AUTHORIZATION_ERROR, att_handle=self.handle
|
|
804
830
|
)
|
|
805
831
|
|
|
806
|
-
if
|
|
832
|
+
if hasattr(self.value, 'read'):
|
|
807
833
|
try:
|
|
808
|
-
value = read(connection)
|
|
834
|
+
value = self.value.read(connection)
|
|
809
835
|
except ATT_Error as error:
|
|
810
836
|
raise ATT_Error(
|
|
811
837
|
error_code=error.error_code, att_handle=self.handle
|
|
@@ -815,7 +841,7 @@ class Attribute(EventEmitter):
|
|
|
815
841
|
|
|
816
842
|
return self.encode_value(value)
|
|
817
843
|
|
|
818
|
-
def write_value(self, connection: Connection, value_bytes):
|
|
844
|
+
def write_value(self, connection: Connection, value_bytes: bytes) -> None:
|
|
819
845
|
if (
|
|
820
846
|
self.permissions & self.WRITE_REQUIRES_ENCRYPTION
|
|
821
847
|
) and not connection.encryption:
|
|
@@ -836,9 +862,9 @@ class Attribute(EventEmitter):
|
|
|
836
862
|
|
|
837
863
|
value = self.decode_value(value_bytes)
|
|
838
864
|
|
|
839
|
-
if
|
|
865
|
+
if hasattr(self.value, 'write'):
|
|
840
866
|
try:
|
|
841
|
-
write(connection, value) # pylint: disable=not-callable
|
|
867
|
+
self.value.write(connection, value) # pylint: disable=not-callable
|
|
842
868
|
except ATT_Error as error:
|
|
843
869
|
raise ATT_Error(
|
|
844
870
|
error_code=error.error_code, att_handle=self.handle
|
|
@@ -1186,8 +1186,8 @@ class Device(CompositeEventEmitter):
|
|
|
1186
1186
|
def create_l2cap_registrar(self, psm):
|
|
1187
1187
|
return lambda handler: self.register_l2cap_server(psm, handler)
|
|
1188
1188
|
|
|
1189
|
-
def register_l2cap_server(self, psm, server):
|
|
1190
|
-
self.l2cap_channel_manager.register_server(psm, server)
|
|
1189
|
+
def register_l2cap_server(self, psm, server) -> int:
|
|
1190
|
+
return self.l2cap_channel_manager.register_server(psm, server)
|
|
1191
1191
|
|
|
1192
1192
|
def register_l2cap_channel_server(
|
|
1193
1193
|
self,
|
|
@@ -2758,7 +2758,9 @@ class Device(CompositeEventEmitter):
|
|
|
2758
2758
|
self.abort_on(
|
|
2759
2759
|
'flush',
|
|
2760
2760
|
self.start_advertising(
|
|
2761
|
-
advertising_type=self.advertising_type,
|
|
2761
|
+
advertising_type=self.advertising_type,
|
|
2762
|
+
own_address_type=self.advertising_own_address_type,
|
|
2763
|
+
auto_restart=True,
|
|
2762
2764
|
),
|
|
2763
2765
|
)
|
|
2764
2766
|
|
|
@@ -28,7 +28,7 @@ import enum
|
|
|
28
28
|
import functools
|
|
29
29
|
import logging
|
|
30
30
|
import struct
|
|
31
|
-
from typing import Optional, Sequence, List
|
|
31
|
+
from typing import Optional, Sequence, Iterable, List, Union
|
|
32
32
|
|
|
33
33
|
from .colors import color
|
|
34
34
|
from .core import UUID, get_dict_key_by_value
|
|
@@ -187,7 +187,7 @@ GATT_CENTRAL_ADDRESS_RESOLUTION__CHARACTERISTIC = UUID.from_16_bi
|
|
|
187
187
|
# -----------------------------------------------------------------------------
|
|
188
188
|
|
|
189
189
|
|
|
190
|
-
def show_services(services):
|
|
190
|
+
def show_services(services: Iterable[Service]) -> None:
|
|
191
191
|
for service in services:
|
|
192
192
|
print(color(str(service), 'cyan'))
|
|
193
193
|
|
|
@@ -210,11 +210,11 @@ class Service(Attribute):
|
|
|
210
210
|
|
|
211
211
|
def __init__(
|
|
212
212
|
self,
|
|
213
|
-
uuid,
|
|
213
|
+
uuid: Union[str, UUID],
|
|
214
214
|
characteristics: List[Characteristic],
|
|
215
215
|
primary=True,
|
|
216
216
|
included_services: List[Service] = [],
|
|
217
|
-
):
|
|
217
|
+
) -> None:
|
|
218
218
|
# Convert the uuid to a UUID object if it isn't already
|
|
219
219
|
if isinstance(uuid, str):
|
|
220
220
|
uuid = UUID(uuid)
|
|
@@ -239,7 +239,7 @@ class Service(Attribute):
|
|
|
239
239
|
"""
|
|
240
240
|
return None
|
|
241
241
|
|
|
242
|
-
def __str__(self):
|
|
242
|
+
def __str__(self) -> str:
|
|
243
243
|
return (
|
|
244
244
|
f'Service(handle=0x{self.handle:04X}, '
|
|
245
245
|
f'end=0x{self.end_group_handle:04X}, '
|
|
@@ -255,9 +255,11 @@ class TemplateService(Service):
|
|
|
255
255
|
to expose their UUID as a class property
|
|
256
256
|
'''
|
|
257
257
|
|
|
258
|
-
UUID:
|
|
258
|
+
UUID: UUID
|
|
259
259
|
|
|
260
|
-
def __init__(
|
|
260
|
+
def __init__(
|
|
261
|
+
self, characteristics: List[Characteristic], primary: bool = True
|
|
262
|
+
) -> None:
|
|
261
263
|
super().__init__(self.UUID, characteristics, primary)
|
|
262
264
|
|
|
263
265
|
|
|
@@ -269,7 +271,7 @@ class IncludedServiceDeclaration(Attribute):
|
|
|
269
271
|
|
|
270
272
|
service: Service
|
|
271
273
|
|
|
272
|
-
def __init__(self, service):
|
|
274
|
+
def __init__(self, service: Service) -> None:
|
|
273
275
|
declaration_bytes = struct.pack(
|
|
274
276
|
'<HH2s', service.handle, service.end_group_handle, service.uuid.to_bytes()
|
|
275
277
|
)
|
|
@@ -278,7 +280,7 @@ class IncludedServiceDeclaration(Attribute):
|
|
|
278
280
|
)
|
|
279
281
|
self.service = service
|
|
280
282
|
|
|
281
|
-
def __str__(self):
|
|
283
|
+
def __str__(self) -> str:
|
|
282
284
|
return (
|
|
283
285
|
f'IncludedServiceDefinition(handle=0x{self.handle:04X}, '
|
|
284
286
|
f'group_starting_handle=0x{self.service.handle:04X}, '
|
|
@@ -326,7 +328,7 @@ class Characteristic(Attribute):
|
|
|
326
328
|
f"Characteristic.Properties::from_string() error:\nExpected a string containing any of the keys, separated by , or |: {enum_list_str}\nGot: {properties_str}"
|
|
327
329
|
)
|
|
328
330
|
|
|
329
|
-
def __str__(self):
|
|
331
|
+
def __str__(self) -> str:
|
|
330
332
|
# NOTE: we override this method to offer a consistent result between python
|
|
331
333
|
# versions: the value returned by IntFlag.__str__() changed in version 11.
|
|
332
334
|
return '|'.join(
|
|
@@ -348,10 +350,10 @@ class Characteristic(Attribute):
|
|
|
348
350
|
|
|
349
351
|
def __init__(
|
|
350
352
|
self,
|
|
351
|
-
uuid,
|
|
353
|
+
uuid: Union[str, bytes, UUID],
|
|
352
354
|
properties: Characteristic.Properties,
|
|
353
|
-
permissions,
|
|
354
|
-
value=b'',
|
|
355
|
+
permissions: Union[str, Attribute.Permissions],
|
|
356
|
+
value: Union[str, bytes, CharacteristicValue] = b'',
|
|
355
357
|
descriptors: Sequence[Descriptor] = (),
|
|
356
358
|
):
|
|
357
359
|
super().__init__(uuid, permissions, value)
|
|
@@ -369,7 +371,7 @@ class Characteristic(Attribute):
|
|
|
369
371
|
def has_properties(self, properties: Characteristic.Properties) -> bool:
|
|
370
372
|
return self.properties & properties == properties
|
|
371
373
|
|
|
372
|
-
def __str__(self):
|
|
374
|
+
def __str__(self) -> str:
|
|
373
375
|
return (
|
|
374
376
|
f'Characteristic(handle=0x{self.handle:04X}, '
|
|
375
377
|
f'end=0x{self.end_group_handle:04X}, '
|
|
@@ -386,7 +388,7 @@ class CharacteristicDeclaration(Attribute):
|
|
|
386
388
|
|
|
387
389
|
characteristic: Characteristic
|
|
388
390
|
|
|
389
|
-
def __init__(self, characteristic, value_handle):
|
|
391
|
+
def __init__(self, characteristic: Characteristic, value_handle: int) -> None:
|
|
390
392
|
declaration_bytes = (
|
|
391
393
|
struct.pack('<BH', characteristic.properties, value_handle)
|
|
392
394
|
+ characteristic.uuid.to_pdu_bytes()
|
|
@@ -397,7 +399,7 @@ class CharacteristicDeclaration(Attribute):
|
|
|
397
399
|
self.value_handle = value_handle
|
|
398
400
|
self.characteristic = characteristic
|
|
399
401
|
|
|
400
|
-
def __str__(self):
|
|
402
|
+
def __str__(self) -> str:
|
|
401
403
|
return (
|
|
402
404
|
f'CharacteristicDeclaration(handle=0x{self.handle:04X}, '
|
|
403
405
|
f'value_handle=0x{self.value_handle:04X}, '
|
|
@@ -520,7 +522,7 @@ class CharacteristicAdapter:
|
|
|
520
522
|
|
|
521
523
|
return self.wrapped_characteristic.unsubscribe(subscriber)
|
|
522
524
|
|
|
523
|
-
def __str__(self):
|
|
525
|
+
def __str__(self) -> str:
|
|
524
526
|
wrapped = str(self.wrapped_characteristic)
|
|
525
527
|
return f'{self.__class__.__name__}({wrapped})'
|
|
526
528
|
|
|
@@ -600,10 +602,10 @@ class UTF8CharacteristicAdapter(CharacteristicAdapter):
|
|
|
600
602
|
Adapter that converts strings to/from bytes using UTF-8 encoding
|
|
601
603
|
'''
|
|
602
604
|
|
|
603
|
-
def encode_value(self, value):
|
|
605
|
+
def encode_value(self, value: str) -> bytes:
|
|
604
606
|
return value.encode('utf-8')
|
|
605
607
|
|
|
606
|
-
def decode_value(self, value):
|
|
608
|
+
def decode_value(self, value: bytes) -> str:
|
|
607
609
|
return value.decode('utf-8')
|
|
608
610
|
|
|
609
611
|
|
|
@@ -613,7 +615,7 @@ class Descriptor(Attribute):
|
|
|
613
615
|
See Vol 3, Part G - 3.3.3 Characteristic Descriptor Declarations
|
|
614
616
|
'''
|
|
615
617
|
|
|
616
|
-
def __str__(self):
|
|
618
|
+
def __str__(self) -> str:
|
|
617
619
|
return (
|
|
618
620
|
f'Descriptor(handle=0x{self.handle:04X}, '
|
|
619
621
|
f'type={self.type}, '
|