mirror of
https://github.com/google/bumble.git
synced 2026-06-18 10:12:27 +00:00
formatting and linting automation
Squashed commits: [cd479ba] formatting and linting automation [7fbfabb] formatting and linting automation [c4f9505] fix after rebase [f506ad4] rename job [441d517] update doc (+7 squashed commits) [2e1b416] fix invoke and github action [6ae5bb4] doc for git blame [44b5461] add GitHub action [b07474f] add docs [4cd9a6f] more linter fixes [db71901] wip [540dc88] wip
This commit is contained in:
@@ -20,7 +20,7 @@ import sys
|
||||
import os
|
||||
import logging
|
||||
from colors import color
|
||||
from bumble.device import Device, Peer
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport
|
||||
from bumble.profiles.battery_service import BatteryServiceProxy
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ async def main():
|
||||
print(
|
||||
color('Regulatory Certification:', 'green'),
|
||||
(
|
||||
# pylint: disable-next=line-too-long
|
||||
await device_information_service.ieee_regulatory_certification_data_list.read_value()
|
||||
).hex(),
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ import sys
|
||||
import os
|
||||
import logging
|
||||
from colors import color
|
||||
from bumble.device import Device, Peer
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport
|
||||
from bumble.profiles.heart_rate_service import HeartRateServiceProxy
|
||||
|
||||
|
||||
@@ -76,4 +76,4 @@ input, label {
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -58,4 +58,4 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
+19
-15
@@ -20,8 +20,8 @@ import sys
|
||||
import os
|
||||
import logging
|
||||
import struct
|
||||
import websockets
|
||||
import json
|
||||
import websockets
|
||||
from colors import color
|
||||
|
||||
from bumble.core import AdvertisingData
|
||||
@@ -59,9 +59,10 @@ HID_FEATURE_REPORT = 0x03
|
||||
|
||||
# Report Map
|
||||
HID_KEYBOARD_REPORT_MAP = bytes(
|
||||
# pylint: disable=line-too-long
|
||||
[
|
||||
0x05,
|
||||
0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x01, # Usage Page (Generic Desktop Controls)
|
||||
0x09,
|
||||
0x06, # Usage (Keyboard)
|
||||
0xA1,
|
||||
@@ -69,7 +70,7 @@ HID_KEYBOARD_REPORT_MAP = bytes(
|
||||
0x85,
|
||||
0x01, # . Report ID (1)
|
||||
0x05,
|
||||
0x07, # . Usage Page (Kbrd/Keypad)
|
||||
0x07, # . Usage Page (Keyboard/Keypad)
|
||||
0x19,
|
||||
0xE0, # . Usage Minimum (0xE0)
|
||||
0x29,
|
||||
@@ -99,7 +100,7 @@ HID_KEYBOARD_REPORT_MAP = bytes(
|
||||
0x25,
|
||||
0x94, # . Logical Maximum (0x94)
|
||||
0x05,
|
||||
0x07, # . Usage Page (Kbrd/Keypad)
|
||||
0x07, # . Usage Page (Keyboard/Keypad)
|
||||
0x19,
|
||||
0x00, # . Usage Minimum (0x00)
|
||||
0x29,
|
||||
@@ -130,6 +131,7 @@ HID_KEYBOARD_REPORT_MAP = bytes(
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# pylint: disable=invalid-overridden-method
|
||||
class ServerListener(Device.Listener, Connection.Listener):
|
||||
def __init__(self, device):
|
||||
self.device = device
|
||||
@@ -145,7 +147,7 @@ class ServerListener(Device.Listener, Connection.Listener):
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def on_hid_control_point_write(connection, value):
|
||||
def on_hid_control_point_write(_connection, value):
|
||||
print(f'Control Point Write: {value}')
|
||||
|
||||
|
||||
@@ -295,9 +297,9 @@ async def keyboard_device(device, command):
|
||||
GATT_HID_INFORMATION_CHARACTERISTIC,
|
||||
Characteristic.READ,
|
||||
Characteristic.READABLE,
|
||||
bytes(
|
||||
[0x11, 0x01, 0x00, 0x03]
|
||||
), # bcdHID=1.1, bCountryCode=0x00, Flags=RemoteWake|NormallyConnectable
|
||||
# bcdHID=1.1, bCountryCode=0x00,
|
||||
# Flags=RemoteWake|NormallyConnectable
|
||||
bytes([0x11, 0x01, 0x00, 0x03]),
|
||||
),
|
||||
Characteristic(
|
||||
GATT_HID_CONTROL_POINT_CHARACTERISTIC,
|
||||
@@ -360,7 +362,7 @@ async def keyboard_device(device, command):
|
||||
|
||||
if command == 'web':
|
||||
# Start a Websocket server to receive events from a web page
|
||||
async def serve(websocket, path):
|
||||
async def serve(websocket, _path):
|
||||
while True:
|
||||
try:
|
||||
message = await websocket.recv()
|
||||
@@ -373,7 +375,7 @@ async def keyboard_device(device, command):
|
||||
key = parsed['key']
|
||||
if len(key) == 1:
|
||||
code = ord(key)
|
||||
if code >= ord('a') and code <= ord('z'):
|
||||
if ord('a') <= code <= ord('z'):
|
||||
hid_code = 0x04 + code - ord('a')
|
||||
input_report_characteristic.value = bytes(
|
||||
[0, 0, hid_code, 0, 0, 0, 0, 0]
|
||||
@@ -390,6 +392,7 @@ async def keyboard_device(device, command):
|
||||
except websockets.exceptions.ConnectionClosedOK:
|
||||
pass
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
await websockets.serve(serve, 'localhost', 8989)
|
||||
await asyncio.get_event_loop().create_future()
|
||||
else:
|
||||
@@ -413,11 +416,12 @@ async def keyboard_device(device, command):
|
||||
# -----------------------------------------------------------------------------
|
||||
async def main():
|
||||
if len(sys.argv) < 4:
|
||||
print('Usage: python keyboard.py <device-config> <transport-spec> <command>')
|
||||
print(' where <command> is one of:')
|
||||
print(' connect <address> (run a keyboard host, connecting to a keyboard)')
|
||||
print(
|
||||
' web (run a keyboard with keypress input from a web page, see keyboard.html'
|
||||
'Usage: python keyboard.py <device-config> <transport-spec> <command>'
|
||||
' where <command> is one of:\n'
|
||||
' connect <address> (run a keyboard host, connecting to a keyboard)\n'
|
||||
' web (run a keyboard with keypress input from a web page, '
|
||||
'see keyboard.html\n'
|
||||
)
|
||||
print(
|
||||
' sim (run a keyboard simulation, emitting a canned sequence of keystrokes'
|
||||
@@ -436,7 +440,7 @@ async def main():
|
||||
if command == 'connect':
|
||||
# Run as a Keyboard host
|
||||
await keyboard_host(device, sys.argv[4])
|
||||
elif command in {'sim', 'web'}:
|
||||
elif command in ('sim', 'web'):
|
||||
# Run as a keyboard device
|
||||
await keyboard_device(device, command)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ from bumble.core import (
|
||||
BT_AUDIO_SINK_SERVICE,
|
||||
BT_L2CAP_PROTOCOL_ID,
|
||||
)
|
||||
from bumble.avdtp import Protocol as AVDTP_Protocol, find_avdtp_service_with_connection
|
||||
from bumble.avdtp import Protocol as AVDTP_Protocol
|
||||
from bumble.a2dp import make_audio_source_service_sdp_records
|
||||
from bumble.sdp import (
|
||||
Client as SDP_Client,
|
||||
@@ -52,6 +52,7 @@ def sdp_records():
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# pylint: disable-next=too-many-nested-blocks
|
||||
async def find_a2dp_service(device, connection):
|
||||
# Connect to the SDP Server
|
||||
sdp_client = SDP_Client(device)
|
||||
@@ -101,7 +102,8 @@ async def find_a2dp_service(device, connection):
|
||||
avdtp_version_major = protocol_descriptor.value[1].value >> 8
|
||||
avdtp_version_minor = protocol_descriptor.value[1].value & 0xFF
|
||||
print(
|
||||
f'{color(" AVDTP Version:", "cyan")} {avdtp_version_major}.{avdtp_version_minor}'
|
||||
f'{color(" AVDTP Version:", "cyan")} '
|
||||
f'{avdtp_version_major}.{avdtp_version_minor}'
|
||||
)
|
||||
service_version = (avdtp_version_major, avdtp_version_minor)
|
||||
|
||||
@@ -119,7 +121,8 @@ async def find_a2dp_service(device, connection):
|
||||
bluetooth_profile_descriptor_list.value
|
||||
)
|
||||
else:
|
||||
# Sometimes, instead of a list of lists, we just find a list. Fix that
|
||||
# Sometimes, instead of a list of lists, we just find a list.
|
||||
# Fix that.
|
||||
bluetooth_profile_descriptors = [bluetooth_profile_descriptor_list]
|
||||
|
||||
print(color(' Profiles:', 'green'))
|
||||
@@ -127,7 +130,8 @@ async def find_a2dp_service(device, connection):
|
||||
version_major = bluetooth_profile_descriptor.value[1].value >> 8
|
||||
version_minor = bluetooth_profile_descriptor.value[1].value & 0xFF
|
||||
print(
|
||||
f' {bluetooth_profile_descriptor.value[0].value} - version {version_major}.{version_minor}'
|
||||
f' {bluetooth_profile_descriptor.value[0].value}'
|
||||
f' - version {version_major}.{version_minor}'
|
||||
)
|
||||
|
||||
await sdp_client.disconnect()
|
||||
@@ -152,7 +156,8 @@ async def main():
|
||||
# Start the controller
|
||||
await device.power_on()
|
||||
|
||||
# Setup the SDP to expose a SRC service, in case the remote device queries us back
|
||||
# Setup the SDP to expose a SRC service, in case the remote device queries us
|
||||
# back
|
||||
device.sdp_service_records = sdp_records()
|
||||
|
||||
# Connect to a peer
|
||||
|
||||
@@ -20,7 +20,6 @@ import sys
|
||||
import os
|
||||
import logging
|
||||
|
||||
from colors import color
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.core import BT_BR_EDR_TRANSPORT
|
||||
@@ -92,8 +91,8 @@ def on_avdtp_connection(server):
|
||||
def on_rtp_packet(packet):
|
||||
header = packet.payload[0]
|
||||
fragmented = header >> 7
|
||||
start = (header >> 6) & 0x01
|
||||
last = (header >> 5) & 0x01
|
||||
# start = (header >> 6) & 0x01
|
||||
# last = (header >> 5) & 0x01
|
||||
number_of_frames = header & 0x0F
|
||||
|
||||
if fragmented:
|
||||
@@ -108,7 +107,8 @@ def on_rtp_packet(packet):
|
||||
async def main():
|
||||
if len(sys.argv) < 4:
|
||||
print(
|
||||
'Usage: run_a2dp_sink.py <device-config> <transport-spec> <sbc-file> [<bt-addr>]'
|
||||
'Usage: run_a2dp_sink.py <device-config> <transport-spec> <sbc-file> '
|
||||
'[<bt-addr>]'
|
||||
)
|
||||
print('example: run_a2dp_sink.py classic1.json usb:0 output.sbc')
|
||||
return
|
||||
|
||||
@@ -54,7 +54,8 @@ def sdp_records():
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def codec_capabilities():
|
||||
# NOTE: this shouldn't be hardcoded, but should be inferred from the input file instead
|
||||
# NOTE: this shouldn't be hardcoded, but should be inferred from the input file
|
||||
# instead
|
||||
return MediaCodecCapabilities(
|
||||
media_type=AVDTP_AUDIO_MEDIA_TYPE,
|
||||
media_codec_type=A2DP_SBC_CODEC_TYPE,
|
||||
@@ -116,7 +117,8 @@ async def stream_packets(read_function, protocol):
|
||||
async def main():
|
||||
if len(sys.argv) < 4:
|
||||
print(
|
||||
'Usage: run_a2dp_source.py <device-config> <transport-spec> <sbc-file> [<bluetooth-address>]'
|
||||
'Usage: run_a2dp_source.py <device-config> <transport-spec> <sbc-file> '
|
||||
'[<bluetooth-address>]'
|
||||
)
|
||||
print(
|
||||
'example: run_a2dp_source.py classic1.json usb:0 test.sbc E1:CA:72:48:C4:E8'
|
||||
@@ -138,7 +140,8 @@ async def main():
|
||||
await device.power_on()
|
||||
|
||||
with open(sys.argv[3], 'rb') as sbc_file:
|
||||
# NOTE: this should be using asyncio file reading, but blocking reads are good enough for testing
|
||||
# NOTE: this should be using asyncio file reading, but blocking reads are
|
||||
# good enough for testing
|
||||
async def read(byte_count):
|
||||
return sbc_file.read(byte_count)
|
||||
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
# Imports
|
||||
# -----------------------------------------------------------------------------
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
from bumble.device import AdvertisingType, Device
|
||||
from bumble.hci import Address
|
||||
|
||||
from bumble.hci import *
|
||||
from bumble.controller import *
|
||||
from bumble.device import *
|
||||
from bumble.transport import *
|
||||
from bumble.host import *
|
||||
from bumble.transport import open_transport_or_link
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import logging
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.hci import UUID
|
||||
from bumble.core import UUID
|
||||
from bumble.gatt import Service, Characteristic, CharacteristicValue
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ ASHA_LE_PSM_OUT_CHARACTERISTIC = UUID(
|
||||
async def main():
|
||||
if len(sys.argv) != 4:
|
||||
print(
|
||||
'Usage: python run_asha_sink.py <device-config> <transport-spec> <audio-file>'
|
||||
'Usage: python run_asha_sink.py <device-config> <transport-spec> '
|
||||
'<audio-file>'
|
||||
)
|
||||
print('example: python run_asha_sink.py device1.json usb:0 audio_out.g722')
|
||||
return
|
||||
@@ -62,14 +63,15 @@ async def main():
|
||||
device = Device.from_config_file_with_hci(sys.argv[1], hci_source, hci_sink)
|
||||
|
||||
# Handler for audio control commands
|
||||
def on_audio_control_point_write(connection, value):
|
||||
def on_audio_control_point_write(_connection, value):
|
||||
print('--- AUDIO CONTROL POINT Write:', value.hex())
|
||||
opcode = value[0]
|
||||
if opcode == 1:
|
||||
# Start
|
||||
audio_type = ('Unknown', 'Ringtone', 'Phone Call', 'Media')[value[2]]
|
||||
print(
|
||||
f'### START: codec={value[1]}, audio_type={audio_type}, volume={value[3]}, otherstate={value[4]}'
|
||||
f'### START: codec={value[1]}, audio_type={audio_type}, '
|
||||
f'volume={value[3]}, otherstate={value[4]}'
|
||||
)
|
||||
elif opcode == 2:
|
||||
print('### STOP')
|
||||
@@ -82,7 +84,7 @@ async def main():
|
||||
)
|
||||
|
||||
# Handler for volume control
|
||||
def on_volume_write(connection, value):
|
||||
def on_volume_write(_connection, value):
|
||||
print('--- VOLUME Write:', value[0])
|
||||
|
||||
# Register an L2CAP CoC server
|
||||
|
||||
@@ -35,11 +35,10 @@ from bumble.sdp import (
|
||||
async def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(
|
||||
'Usage: run_classic_connect.py <device-config> <transport-spec> <bluetooth-addresses..>'
|
||||
)
|
||||
print(
|
||||
'example: run_classic_connect.py classic1.json usb:04b4:f901 E1:CA:72:48:C4:E8'
|
||||
'Usage: run_classic_connect.py <device-config> <transport-spec> '
|
||||
'<bluetooth-addresses..>'
|
||||
)
|
||||
print('example: run_classic_connect.py classic1.json usb:0 E1:CA:72:48:C4:E8')
|
||||
return
|
||||
|
||||
print('<<< connecting to HCI...')
|
||||
@@ -74,7 +73,7 @@ async def main():
|
||||
)
|
||||
print(color(f'SERVICE {service_record_handle:04X} attributes:', 'yellow'))
|
||||
for attribute in attributes:
|
||||
print(' ', attribute.to_string(color=True))
|
||||
print(' ', attribute.to_string(with_colors=True))
|
||||
|
||||
# Search for services with an L2CAP service attribute
|
||||
search_result = await sdp_client.search_attributes(
|
||||
@@ -87,7 +86,10 @@ async def main():
|
||||
print(
|
||||
' '
|
||||
+ '\n '.join(
|
||||
[attribute.to_string(color=True) for attribute in attribute_list]
|
||||
[
|
||||
attribute.to_string(with_colors=True)
|
||||
for attribute in attribute_list
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ from bumble.core import DeviceClass
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class DiscoveryListener(Device.Listener):
|
||||
def on_inquiry_result(self, address, class_of_device, eir_data, rssi):
|
||||
def on_inquiry_result(self, address, class_of_device, data, rssi):
|
||||
(
|
||||
service_classes,
|
||||
major_device_class,
|
||||
@@ -37,18 +37,19 @@ class DiscoveryListener(Device.Listener):
|
||||
separator = '\n '
|
||||
print(f'>>> {color(address, "yellow")}:')
|
||||
print(f' Device Class (raw): {class_of_device:06X}')
|
||||
print(
|
||||
f' Device Major Class: {DeviceClass.major_device_class_name(major_device_class)}'
|
||||
major_class_name = DeviceClass.major_device_class_name(major_device_class)
|
||||
print(' Device Major Class: ' f'{major_class_name}')
|
||||
minor_class_name = DeviceClass.minor_device_class_name(
|
||||
major_device_class, minor_device_class
|
||||
)
|
||||
print(' Device Minor Class: ' f'{minor_class_name}')
|
||||
print(
|
||||
f' Device Minor Class: {DeviceClass.minor_device_class_name(major_device_class, minor_device_class)}'
|
||||
)
|
||||
print(
|
||||
f' Device Services: {", ".join(DeviceClass.service_class_labels(service_classes))}'
|
||||
' Device Services: '
|
||||
f'{", ".join(DeviceClass.service_class_labels(service_classes))}'
|
||||
)
|
||||
print(f' RSSI: {rssi}')
|
||||
if eir_data.ad_structures:
|
||||
print(f' {eir_data.to_string(separator)}')
|
||||
if data.ad_structures:
|
||||
print(f' {data.to_string(separator)}')
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@@ -28,7 +28,8 @@ from bumble.transport import open_transport_or_link
|
||||
async def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(
|
||||
'Usage: run_connect_and_encrypt.py <device-config> <transport-spec> <bluetooth-address>'
|
||||
'Usage: run_connect_and_encrypt.py <device-config> <transport-spec> '
|
||||
'<bluetooth-address>'
|
||||
)
|
||||
print(
|
||||
'example: run_connect_and_encrypt.py device1.json usb:0 E1:CA:72:48:C4:E8'
|
||||
|
||||
@@ -20,12 +20,18 @@ import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
from bumble.hci import *
|
||||
from bumble.controller import *
|
||||
from bumble.host import *
|
||||
from bumble.device import *
|
||||
from bumble.transport import *
|
||||
from bumble.link import *
|
||||
from bumble.gatt import (
|
||||
GATT_CHARACTERISTIC_USER_DESCRIPTION_DESCRIPTOR,
|
||||
GATT_DEVICE_INFORMATION_SERVICE,
|
||||
GATT_MANUFACTURER_NAME_STRING_CHARACTERISTIC,
|
||||
Characteristic,
|
||||
Descriptor,
|
||||
Service,
|
||||
)
|
||||
from bumble.device import Device
|
||||
from bumble.host import Host
|
||||
from bumble.controller import Controller
|
||||
from bumble.link import LocalLink
|
||||
from bumble.transport import open_transport_or_link
|
||||
|
||||
|
||||
@@ -33,10 +39,12 @@ from bumble.transport import open_transport_or_link
|
||||
async def main():
|
||||
if len(sys.argv) != 4:
|
||||
print(
|
||||
'Usage: run_controller.py <controller-address> <device-config> <transport-spec>'
|
||||
'Usage: run_controller.py <controller-address> <device-config> '
|
||||
'<transport-spec>'
|
||||
)
|
||||
print(
|
||||
'example: run_controller.py F2:F3:F4:F5:F6:F7 device1.json udp:0.0.0.0:22333,172.16.104.161:22333'
|
||||
'example: run_controller.py F2:F3:F4:F5:F6:F7 device1.json '
|
||||
'udp:0.0.0.0:22333,172.16.104.161:22333'
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@@ -38,7 +38,9 @@ class ScannerListener(Device.Listener):
|
||||
type_color = 'cyan'
|
||||
|
||||
print(
|
||||
f'>>> {color(advertisement.address, address_color)} [{color(address_type_string, type_color)}]: RSSI={advertisement.rssi}, {advertisement.data}'
|
||||
f'>>> {color(advertisement.address, address_color)} '
|
||||
f'[{color(address_type_string, type_color)}]: '
|
||||
f'RSSI={advertisement.rssi}, {advertisement.data}'
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ class Listener(Device.Listener):
|
||||
self.device = device
|
||||
|
||||
@AsyncRunner.run_in_task()
|
||||
# pylint: disable=invalid-overridden-method
|
||||
async def on_connection(self, connection):
|
||||
print(f'=== Connected to {connection}')
|
||||
|
||||
@@ -71,7 +72,8 @@ class Listener(Device.Listener):
|
||||
async def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(
|
||||
'Usage: run_gatt_client.py <device-config> <transport-spec> [<bluetooth-address>]'
|
||||
'Usage: run_gatt_client.py <device-config> <transport-spec> '
|
||||
'[<bluetooth-address>]'
|
||||
)
|
||||
print('example: run_gatt_client.py device1.json usb:0 E1:CA:72:48:C4:E8')
|
||||
return
|
||||
|
||||
@@ -60,8 +60,8 @@ def my_custom_read_with_error(connection):
|
||||
print('----- READ from', connection, '[returning error]')
|
||||
if connection.is_encrypted:
|
||||
return bytes([123])
|
||||
else:
|
||||
raise ATT_Error(ATT_INSUFFICIENT_ENCRYPTION_ERROR)
|
||||
|
||||
raise ATT_Error(ATT_INSUFFICIENT_ENCRYPTION_ERROR)
|
||||
|
||||
|
||||
def my_custom_write_with_error(connection, value):
|
||||
@@ -74,7 +74,8 @@ def my_custom_write_with_error(connection, value):
|
||||
async def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(
|
||||
'Usage: run_gatt_server.py <device-config> <transport-spec> [<bluetooth-address>]'
|
||||
'Usage: run_gatt_server.py <device-config> <transport-spec> '
|
||||
'[<bluetooth-address>]'
|
||||
)
|
||||
print('example: run_gatt_server.py device1.json usb:0 E1:CA:72:48:C4:E8')
|
||||
return
|
||||
|
||||
+21
-10
@@ -21,9 +21,15 @@ import os
|
||||
import logging
|
||||
|
||||
from colors import color
|
||||
|
||||
import bumble.core
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.core import ConnectionError, BT_BR_EDR_TRANSPORT
|
||||
from bumble.core import (
|
||||
BT_HANDSFREE_SERVICE,
|
||||
BT_RFCOMM_PROTOCOL_ID,
|
||||
BT_BR_EDR_TRANSPORT,
|
||||
)
|
||||
from bumble.rfcomm import Client
|
||||
from bumble.sdp import (
|
||||
Client as SDP_Client,
|
||||
@@ -33,11 +39,11 @@ from bumble.sdp import (
|
||||
SDP_SERVICE_CLASS_ID_LIST_ATTRIBUTE_ID,
|
||||
SDP_BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRIBUTE_ID,
|
||||
)
|
||||
from bumble.hci import BT_HANDSFREE_SERVICE, BT_RFCOMM_PROTOCOL_ID
|
||||
from bumble.hfp import HfpProtocol
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# pylint: disable-next=too-many-nested-blocks
|
||||
async def list_rfcomm_channels(device, connection):
|
||||
# Connect to the SDP Server
|
||||
sdp_client = SDP_Client(device)
|
||||
@@ -55,6 +61,7 @@ async def list_rfcomm_channels(device, connection):
|
||||
print(color('==================================', 'blue'))
|
||||
print(color('Handsfree Services:', 'yellow'))
|
||||
rfcomm_channels = []
|
||||
# pylint: disable-next=too-many-nested-blocks
|
||||
for attribute_list in search_result:
|
||||
# Look for the RFCOMM Channel number
|
||||
protocol_descriptor_list = ServiceAttribute.find_attribute_in_list(
|
||||
@@ -88,7 +95,8 @@ async def list_rfcomm_channels(device, connection):
|
||||
bluetooth_profile_descriptor_list.value
|
||||
)
|
||||
else:
|
||||
# Sometimes, instead of a list of lists, we just find a list. Fix that
|
||||
# Sometimes, instead of a list of lists, we just
|
||||
# find a list. Fix that
|
||||
bluetooth_profile_descriptors = [
|
||||
bluetooth_profile_descriptor_list
|
||||
]
|
||||
@@ -105,7 +113,9 @@ async def list_rfcomm_channels(device, connection):
|
||||
& 0xFF
|
||||
)
|
||||
print(
|
||||
f' {bluetooth_profile_descriptor.value[0].value} - version {version_major}.{version_minor}'
|
||||
' '
|
||||
f'{bluetooth_profile_descriptor.value[0].value}'
|
||||
f' - version {version_major}.{version_minor}'
|
||||
)
|
||||
|
||||
# List service classes
|
||||
@@ -126,14 +136,13 @@ async def list_rfcomm_channels(device, connection):
|
||||
async def main():
|
||||
if len(sys.argv) < 4:
|
||||
print(
|
||||
'Usage: run_hfp_gateway.py <device-config> <transport-spec> <bluetooth-address>'
|
||||
'Usage: run_hfp_gateway.py <device-config> <transport-spec> '
|
||||
'<bluetooth-address>'
|
||||
)
|
||||
print(
|
||||
' specifying a channel number, or "discover" to list all RFCOMM channels'
|
||||
)
|
||||
print(
|
||||
'example: run_hfp_gateway.py hfp_gateway.json usb:04b4:f901 E1:CA:72:48:C4:E8'
|
||||
)
|
||||
print('example: run_hfp_gateway.py hfp_gateway.json usb:0 E1:CA:72:48:C4:E8')
|
||||
return
|
||||
|
||||
print('<<< connecting to HCI...')
|
||||
@@ -180,7 +189,7 @@ async def main():
|
||||
try:
|
||||
session = await rfcomm_mux.open_dlc(channel)
|
||||
print('### Session open', session)
|
||||
except ConnectionError as error:
|
||||
except bumble.core.ConnectionError as error:
|
||||
print(f'### Session open failed: {error}')
|
||||
await rfcomm_mux.disconnect()
|
||||
print('@@@ Disconnected from RFCOMM server')
|
||||
@@ -196,7 +205,9 @@ async def main():
|
||||
protocol.send_response_line('OK')
|
||||
elif line.startswith('AT+CIND=?'):
|
||||
protocol.send_response_line(
|
||||
'+CIND: ("call",(0,1)),("callsetup",(0-3)),("service",(0-1)),("signal",(0-5)),("roam",(0,1)),("battchg",(0-5)),("callheld",(0-2))'
|
||||
'+CIND: ("call",(0,1)),("callsetup",(0-3)),("service",(0-1)),'
|
||||
'("signal",(0-5)),("roam",(0,1)),("battchg",(0-5)),'
|
||||
'("callheld",(0-2))'
|
||||
)
|
||||
protocol.send_response_line('OK')
|
||||
elif line.startswith('AT+CIND?'):
|
||||
|
||||
@@ -19,13 +19,13 @@ import asyncio
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
import websockets
|
||||
import json
|
||||
import websockets
|
||||
|
||||
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.rfcomm import Server as RfommServer
|
||||
from bumble.rfcomm import Server as RfcommServer
|
||||
from bumble.sdp import (
|
||||
DataElement,
|
||||
ServiceAttribute,
|
||||
@@ -97,7 +97,7 @@ class UiServer:
|
||||
|
||||
async def start(self):
|
||||
# Start a Websocket server to receive events from a web page
|
||||
async def serve(websocket, path):
|
||||
async def serve(websocket, _path):
|
||||
while True:
|
||||
try:
|
||||
message = await websocket.recv()
|
||||
@@ -112,6 +112,7 @@ class UiServer:
|
||||
except websockets.exceptions.ConnectionClosedOK:
|
||||
pass
|
||||
|
||||
# pylint: disable=no-member
|
||||
await websockets.serve(serve, 'localhost', 8989)
|
||||
|
||||
|
||||
@@ -147,7 +148,7 @@ async def main():
|
||||
device.classic_enabled = True
|
||||
|
||||
# Create and register a server
|
||||
rfcomm_server = RfommServer(device)
|
||||
rfcomm_server = RfcommServer(device)
|
||||
|
||||
# Listen for incoming DLC connections
|
||||
channel_number = rfcomm_server.listen(on_dlc)
|
||||
|
||||
@@ -42,7 +42,8 @@ class Listener(Device.Listener, Connection.Listener):
|
||||
self, connection, characteristic, notify_enabled, indicate_enabled
|
||||
):
|
||||
print(
|
||||
f'$$$ Characteristic subscription for handle {characteristic.handle} from {connection}: '
|
||||
f'$$$ Characteristic subscription for handle {characteristic.handle} '
|
||||
f'from {connection}: '
|
||||
f'notify {"enabled" if notify_enabled else "disabled"}, '
|
||||
f'indicate {"enabled" if indicate_enabled else "disabled"}'
|
||||
)
|
||||
|
||||
@@ -21,9 +21,15 @@ import os
|
||||
import logging
|
||||
|
||||
from colors import color
|
||||
|
||||
import bumble.core
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.core import ConnectionError, BT_BR_EDR_TRANSPORT
|
||||
from bumble.core import (
|
||||
BT_L2CAP_PROTOCOL_ID,
|
||||
BT_RFCOMM_PROTOCOL_ID,
|
||||
BT_BR_EDR_TRANSPORT,
|
||||
)
|
||||
from bumble.rfcomm import Client
|
||||
from bumble.sdp import (
|
||||
Client as SDP_Client,
|
||||
@@ -33,7 +39,6 @@ from bumble.sdp import (
|
||||
SDP_SERVICE_CLASS_ID_LIST_ATTRIBUTE_ID,
|
||||
SDP_BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRIBUTE_ID,
|
||||
)
|
||||
from bumble.hci import BT_L2CAP_PROTOCOL_ID, BT_RFCOMM_PROTOCOL_ID
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -53,6 +58,7 @@ async def list_rfcomm_channels(device, connection):
|
||||
)
|
||||
print(color('==================================', 'blue'))
|
||||
print(color('RFCOMM Services:', 'yellow'))
|
||||
# pylint: disable-next=too-many-nested-blocks
|
||||
for attribute_list in search_result:
|
||||
# Look for the RFCOMM Channel number
|
||||
protocol_descriptor_list = ServiceAttribute.find_attribute_in_list(
|
||||
@@ -85,7 +91,8 @@ async def list_rfcomm_channels(device, connection):
|
||||
bluetooth_profile_descriptor_list.value
|
||||
)
|
||||
else:
|
||||
# Sometimes, instead of a list of lists, we just find a list. Fix that
|
||||
# Sometimes, instead of a list of lists, we just
|
||||
# find a list. Fix that
|
||||
bluetooth_profile_descriptors = [
|
||||
bluetooth_profile_descriptor_list
|
||||
]
|
||||
@@ -102,7 +109,9 @@ async def list_rfcomm_channels(device, connection):
|
||||
& 0xFF
|
||||
)
|
||||
print(
|
||||
f' {bluetooth_profile_descriptor.value[0].value} - version {version_major}.{version_minor}'
|
||||
' '
|
||||
f'{bluetooth_profile_descriptor.value[0].value}'
|
||||
f' - version {version_major}.{version_minor}'
|
||||
)
|
||||
|
||||
# List service classes
|
||||
@@ -122,10 +131,11 @@ async def list_rfcomm_channels(device, connection):
|
||||
class TcpServerProtocol(asyncio.Protocol):
|
||||
def __init__(self, rfcomm_session):
|
||||
self.rfcomm_session = rfcomm_session
|
||||
self.transport = None
|
||||
|
||||
def connection_made(self, transport):
|
||||
peername = transport.get_extra_info('peername')
|
||||
print(f'<<< TCP Server: connection from {peername}')
|
||||
peer_name = transport.get_extra_info('peer_name')
|
||||
print(f'<<< TCP Server: connection from {peer_name}')
|
||||
self.transport = transport
|
||||
self.rfcomm_session.sink = self.rfcomm_data_received
|
||||
|
||||
@@ -158,14 +168,13 @@ async def tcp_server(tcp_port, rfcomm_session):
|
||||
async def main():
|
||||
if len(sys.argv) < 5:
|
||||
print(
|
||||
'Usage: run_rfcomm_client.py <device-config> <transport-spec> <bluetooth-address> <channel>|discover [tcp-port]'
|
||||
'Usage: run_rfcomm_client.py <device-config> <transport-spec> '
|
||||
'<bluetooth-address> <channel>|discover [tcp-port]'
|
||||
)
|
||||
print(
|
||||
' specifying a channel number, or "discover" to list all RFCOMM channels'
|
||||
)
|
||||
print(
|
||||
'example: run_rfcomm_client.py classic1.json usb:04b4:f901 E1:CA:72:48:C4:E8 8'
|
||||
)
|
||||
print('example: run_rfcomm_client.py classic1.json usb:0 E1:CA:72:48:C4:E8 8')
|
||||
return
|
||||
|
||||
print('<<< connecting to HCI...')
|
||||
@@ -209,7 +218,7 @@ async def main():
|
||||
try:
|
||||
session = await rfcomm_mux.open_dlc(channel)
|
||||
print('### Session open', session)
|
||||
except ConnectionError as error:
|
||||
except bumble.core.ConnectionError as error:
|
||||
print(f'### Session open failed: {error}')
|
||||
await rfcomm_mux.disconnect()
|
||||
print('@@@ Disconnected from RFCOMM server')
|
||||
|
||||
@@ -22,7 +22,7 @@ import logging
|
||||
|
||||
from bumble.device import Device
|
||||
from bumble.transport import open_transport_or_link
|
||||
from bumble.core import UUID
|
||||
from bumble.core import BT_L2CAP_PROTOCOL_ID, BT_RFCOMM_PROTOCOL_ID, UUID
|
||||
from bumble.rfcomm import Server
|
||||
from bumble.sdp import (
|
||||
DataElement,
|
||||
@@ -33,7 +33,6 @@ from bumble.sdp import (
|
||||
SDP_SERVICE_CLASS_ID_LIST_ATTRIBUTE_ID,
|
||||
SDP_PROTOCOL_DESCRIPTOR_LIST_ATTRIBUTE_ID,
|
||||
)
|
||||
from bumble.hci import BT_L2CAP_PROTOCOL_ID, BT_RFCOMM_PROTOCOL_ID
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@@ -60,7 +60,11 @@ async def main():
|
||||
|
||||
separator = '\n '
|
||||
print(
|
||||
f'>>> {color(advertisement.address, address_color)} [{color(address_type_string, type_color)}]{address_qualifier}:{separator}RSSI:{advertisement.rssi}{separator}{advertisement.data.to_string(separator)}'
|
||||
f'>>> {color(advertisement.address, address_color)} '
|
||||
f'[{color(address_type_string, type_color)}]'
|
||||
f'{address_qualifier}:{separator}RSSI:{advertisement.rssi}'
|
||||
f'{separator}'
|
||||
f'{advertisement.data.to_string(separator)}'
|
||||
)
|
||||
|
||||
await device.power_on()
|
||||
|
||||
Reference in New Issue
Block a user