Upgrade websockets dependency to 15.0.1+

This commit is contained in:
Josh Wu
2025-10-31 17:25:35 +08:00
parent 1982168a9f
commit d43f5573a6
12 changed files with 57 additions and 45 deletions

View File

@@ -22,6 +22,7 @@ import contextlib
import io import io
import logging import logging
import struct import struct
from collections.abc import Awaitable, Callable
from typing import Any, ContextManager, Optional, Protocol from typing import Any, ContextManager, Optional, Protocol
from bumble import core, hci from bumble import core, hci
@@ -389,15 +390,17 @@ class PumpedPacketSource(ParserSource):
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
class PumpedPacketSink: class PumpedPacketSink:
def __init__(self, send): pump_task: Optional[asyncio.Task[None]]
def __init__(self, send: Callable[[bytes], Awaitable[Any]]):
self.send_function = send self.send_function = send
self.packet_queue = asyncio.Queue() self.packet_queue = asyncio.Queue[bytes]()
self.pump_task = None self.pump_task = None
def on_packet(self, packet: bytes) -> None: def on_packet(self, packet: bytes) -> None:
self.packet_queue.put_nowait(packet) self.packet_queue.put_nowait(packet)
def start(self): def start(self) -> None:
async def pump_packets(): async def pump_packets():
while True: while True:
try: try:

View File

@@ -17,7 +17,7 @@
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
import logging import logging
import websockets.client import websockets.asyncio.client
from bumble.transport.common import ( from bumble.transport.common import (
PumpedPacketSink, PumpedPacketSink,
@@ -42,7 +42,7 @@ async def open_ws_client_transport(spec: str) -> Transport:
Example: ws://localhost:7681/v1/websocket/bt Example: ws://localhost:7681/v1/websocket/bt
''' '''
websocket = await websockets.client.connect(spec) websocket = await websockets.asyncio.client.connect(spec)
class WsTransport(PumpedTransport): class WsTransport(PumpedTransport):
async def close(self): async def close(self):

View File

@@ -16,8 +16,9 @@
# Imports # Imports
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
import logging import logging
from typing import Optional
import websockets import websockets.asyncio.server
from bumble.transport.common import ParserSource, PumpedPacketSink, Transport from bumble.transport.common import ParserSource, PumpedPacketSink, Transport
@@ -40,7 +41,12 @@ async def open_ws_server_transport(spec: str) -> Transport:
''' '''
class WsServerTransport(Transport): class WsServerTransport(Transport):
def __init__(self): sink: PumpedPacketSink
source: ParserSource
connection: Optional[websockets.asyncio.server.ServerConnection]
server: Optional[websockets.asyncio.server.Server]
def __init__(self) -> None:
source = ParserSource() source = ParserSource()
sink = PumpedPacketSink(self.send_packet) sink = PumpedPacketSink(self.send_packet)
self.connection = None self.connection = None
@@ -48,17 +54,19 @@ async def open_ws_server_transport(spec: str) -> Transport:
super().__init__(source, sink) super().__init__(source, sink)
async def serve(self, local_host, local_port): async def serve(self, local_host: str, local_port: str) -> None:
self.sink.start() self.sink.start()
# pylint: disable-next=no-member # pylint: disable-next=no-member
self.server = await websockets.serve( self.server = await websockets.asyncio.server.serve(
ws_handler=self.on_connection, handler=self.on_connection,
host=local_host if local_host != '_' else None, host=local_host if local_host != '_' else None,
port=int(local_port), port=int(local_port),
) )
logger.debug(f'websocket server ready on port {local_port}') logger.debug(f'websocket server ready on port {local_port}')
async def on_connection(self, connection): async def on_connection(
self, connection: websockets.asyncio.server.ServerConnection
) -> None:
logger.debug( logger.debug(
f'new connection on {connection.local_address} ' f'new connection on {connection.local_address} '
f'from {connection.remote_address}' f'from {connection.remote_address}'
@@ -77,11 +85,11 @@ async def open_ws_server_transport(spec: str) -> Transport:
# We're now disconnected # We're now disconnected
self.connection = None self.connection = None
async def send_packet(self, packet): async def send_packet(self, packet: bytes) -> None:
if self.connection is None: if self.connection is None:
logger.debug('no connection, dropping packet') logger.debug('no connection, dropping packet')
return return
return await self.connection.send(packet) await self.connection.send(packet)
local_host, local_port = spec.rsplit(':', maxsplit=1) local_host, local_port = spec.rsplit(':', maxsplit=1)
transport = WsServerTransport() transport = WsServerTransport()

View File

@@ -20,7 +20,7 @@ import json
import struct import struct
import sys import sys
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import data_types from bumble import data_types
@@ -367,7 +367,7 @@ async def keyboard_device(device, command):
if command == 'web': if command == 'web':
# Start a Websocket server to receive events from a web page # Start a Websocket server to receive events from a web page
async def serve(websocket, _path): async def serve(websocket: websockets.asyncio.server.ServerConnection):
while True: while True:
try: try:
message = await websocket.recv() message = await websocket.recv()
@@ -398,7 +398,7 @@ async def keyboard_device(device, command):
pass pass
# pylint: disable-next=no-member # pylint: disable-next=no-member
await websockets.serve(serve, 'localhost', 8989) await websockets.asyncio.server.serve(serve, 'localhost', 8989)
await asyncio.get_event_loop().create_future() await asyncio.get_event_loop().create_future()
else: else:
message = bytes('hello', 'ascii') message = bytes('hello', 'ascii')

View File

@@ -20,7 +20,7 @@ import logging
import sys import sys
from typing import Optional from typing import Optional
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import data_types, decoder, gatt from bumble import data_types, decoder, gatt
@@ -29,12 +29,11 @@ from bumble.device import AdvertisingParameters, Device
from bumble.profiles import asha from bumble.profiles import asha
from bumble.transport import open_transport from bumble.transport import open_transport
ws_connection: Optional[websockets.WebSocketServerProtocol] = None ws_connection: Optional[websockets.asyncio.server.ServerConnection] = None
g722_decoder = decoder.G722Decoder() g722_decoder = decoder.G722Decoder()
async def ws_server(ws_client: websockets.WebSocketServerProtocol, path: str): async def ws_server(ws_client: websockets.asyncio.server.ServerConnection):
del path
global ws_connection global ws_connection
ws_connection = ws_client ws_connection = ws_client
@@ -100,7 +99,7 @@ async def main() -> None:
), ),
) )
await websockets.serve(ws_server, port=8888) await websockets.asyncio.server.serve(ws_server, port=8888)
await hci_transport.source.terminated await hci_transport.source.terminated

View File

@@ -21,8 +21,9 @@ import asyncio
import json import json
import logging import logging
import sys import sys
from typing import Optional
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import a2dp, avc, avdtp, avrcp, utils from bumble import a2dp, avc, avdtp, avrcp, utils
@@ -217,6 +218,8 @@ def on_avrcp_start(avrcp_protocol: avrcp.Protocol, websocket_server: WebSocketSe
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
class WebSocketServer: class WebSocketServer:
socket: Optional[websockets.asyncio.server.ServerConnection]
def __init__( def __init__(
self, avrcp_protocol: avrcp.Protocol, avrcp_delegate: Delegate self, avrcp_protocol: avrcp.Protocol, avrcp_delegate: Delegate
) -> None: ) -> None:
@@ -227,9 +230,9 @@ class WebSocketServer:
async def start(self) -> None: async def start(self) -> None:
# pylint: disable-next=no-member # pylint: disable-next=no-member
await websockets.serve(self.serve, 'localhost', 8989) # type: ignore await websockets.asyncio.server.serve(self.serve, 'localhost', 8989) # type: ignore
async def serve(self, socket, _path) -> None: async def serve(self, socket: websockets.asyncio.server.ServerConnection) -> None:
print('### WebSocket connected') print('### WebSocket connected')
self.socket = socket self.socket = socket
while True: while True:

View File

@@ -22,7 +22,7 @@ import logging
import sys import sys
from typing import Iterable, Optional from typing import Iterable, Optional
import websockets import websockets.asyncio.server
import bumble.core import bumble.core
import bumble.logging import bumble.logging
@@ -33,7 +33,7 @@ from bumble.transport import open_transport
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
ws: Optional[websockets.WebSocketServerProtocol] = None ws: Optional[websockets.asyncio.server.ServerConnection] = None
ag_protocol: Optional[hfp.AgProtocol] = None ag_protocol: Optional[hfp.AgProtocol] = None
source_file: Optional[io.BufferedReader] = None source_file: Optional[io.BufferedReader] = None
@@ -114,8 +114,7 @@ def on_hfp_state_change(connected: bool):
send_message(type='hfp_state_change', connected=connected) send_message(type='hfp_state_change', connected=connected)
async def ws_server(ws_client: websockets.WebSocketServerProtocol, path: str): async def ws_server(ws_client: websockets.asyncio.server.ServerConnection):
del path
global ws global ws
ws = ws_client ws = ws_client
@@ -273,7 +272,7 @@ async def main() -> None:
on_dlc(session) on_dlc(session)
await websockets.serve(ws_server, port=8888) await websockets.asyncio.server.serve(ws_server, port=8888)
if len(sys.argv) >= 5: if len(sys.argv) >= 5:
global source_file global source_file

View File

@@ -22,7 +22,7 @@ import json
import sys import sys
from typing import Optional from typing import Optional
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import hci, hfp, rfcomm from bumble import hci, hfp, rfcomm
@@ -30,7 +30,7 @@ from bumble.device import Connection, Device
from bumble.hfp import HfProtocol from bumble.hfp import HfProtocol
from bumble.transport import open_transport from bumble.transport import open_transport
ws: Optional[websockets.WebSocketServerProtocol] = None ws: Optional[websockets.asyncio.server.ServerConnection] = None
hf_protocol: Optional[HfProtocol] = None hf_protocol: Optional[HfProtocol] = None
@@ -143,7 +143,7 @@ async def main() -> None:
await device.set_connectable(True) await device.set_connectable(True)
# Start the UI websocket server to offer a few buttons and input boxes # Start the UI websocket server to offer a few buttons and input boxes
async def serve(websocket: websockets.WebSocketServerProtocol, _path): async def serve(websocket: websockets.asyncio.server.ServerConnection):
global ws global ws
ws = websocket ws = websocket
async for message in websocket: async for message in websocket:
@@ -166,7 +166,7 @@ async def main() -> None:
response = str(await hf_protocol.query_current_calls()) response = str(await hf_protocol.query_current_calls())
await websocket.send(response) await websocket.send(response)
await websockets.serve(serve, 'localhost', 8989) await websockets.asyncio.server.serve(serve, 'localhost', 8989)
await hci_transport.source.wait_for_termination() await hci_transport.source.wait_for_termination()

View File

@@ -20,7 +20,7 @@ import json
import struct import struct
import sys import sys
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble.core import ( from bumble.core import (
@@ -425,7 +425,7 @@ deviceData = DeviceData()
async def keyboard_device(hid_device: HID_Device): async def keyboard_device(hid_device: HID_Device):
# Start a Websocket server to receive events from a web page # Start a Websocket server to receive events from a web page
async def serve(websocket, _path): async def serve(websocket: websockets.asyncio.server.ServerConnection):
global deviceData global deviceData
while True: while True:
try: try:
@@ -476,7 +476,7 @@ async def keyboard_device(hid_device: HID_Device):
pass pass
# pylint: disable-next=no-member # pylint: disable-next=no-member
await websockets.serve(serve, 'localhost', 8989) await websockets.asyncio.server.serve(serve, 'localhost', 8989)
await asyncio.get_event_loop().create_future() await asyncio.get_event_loop().create_future()

View File

@@ -20,7 +20,7 @@ import json
import sys import sys
from typing import Optional from typing import Optional
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import data_types from bumble import data_types
@@ -101,7 +101,7 @@ async def main() -> None:
) )
device.add_service(AudioStreamControlService(device, sink_ase_id=[1])) device.add_service(AudioStreamControlService(device, sink_ase_id=[1]))
ws: Optional[websockets.WebSocketServerProtocol] = None ws: Optional[websockets.asyncio.server.ServerConnection] = None
mcp: Optional[MediaControlServiceProxy] = None mcp: Optional[MediaControlServiceProxy] = None
advertising_data = bytes( advertising_data = bytes(
@@ -162,7 +162,7 @@ async def main() -> None:
device.on('connection', on_connection) device.on('connection', on_connection)
async def serve(websocket: websockets.WebSocketServerProtocol, _path): async def serve(websocket: websockets.asyncio.server.ServerConnection):
nonlocal ws nonlocal ws
ws = websocket ws = websocket
async for message in websocket: async for message in websocket:
@@ -173,7 +173,7 @@ async def main() -> None:
) )
ws = None ws = None
await websockets.serve(serve, 'localhost', 8989) await websockets.asyncio.server.serve(serve, 'localhost', 8989)
await hci_transport.source.terminated await hci_transport.source.terminated

View File

@@ -21,7 +21,7 @@ import secrets
import sys import sys
from typing import Optional from typing import Optional
import websockets import websockets.asyncio.server
import bumble.logging import bumble.logging
from bumble import data_types from bumble import data_types
@@ -110,7 +110,7 @@ async def main() -> None:
vcs = VolumeControlService() vcs = VolumeControlService()
device.add_service(vcs) device.add_service(vcs)
ws: Optional[websockets.WebSocketServerProtocol] = None ws: Optional[websockets.asyncio.server.ServerConnection] = None
def on_volume_state_change(): def on_volume_state_change():
if ws: if ws:
@@ -152,7 +152,7 @@ async def main() -> None:
advertising_data=advertising_data, advertising_data=advertising_data,
) )
async def serve(websocket: websockets.WebSocketServerProtocol, _path): async def serve(websocket: websockets.asyncio.server.ServerConnection):
nonlocal ws nonlocal ws
await websocket.send( await websocket.send(
dumps_volume_state(vcs.volume_setting, vcs.muted, vcs.change_counter) dumps_volume_state(vcs.volume_setting, vcs.muted, vcs.change_counter)
@@ -166,7 +166,7 @@ async def main() -> None:
await device.notify_subscribers(vcs.volume_state) await device.notify_subscribers(vcs.volume_state)
ws = None ws = None
await websockets.serve(serve, 'localhost', 8989) await websockets.asyncio.server.serve(serve, 'localhost', 8989)
await hci_transport.source.terminated await hci_transport.source.terminated

View File

@@ -32,7 +32,7 @@ dependencies = [
"pyserial-asyncio >= 0.5; platform_system!='Emscripten'", "pyserial-asyncio >= 0.5; platform_system!='Emscripten'",
"pyserial >= 3.5; platform_system!='Emscripten'", "pyserial >= 3.5; platform_system!='Emscripten'",
"pyusb >= 1.2; platform_system!='Emscripten'", "pyusb >= 1.2; platform_system!='Emscripten'",
"websockets == 13.1; platform_system!='Emscripten'", "websockets >= 15.0.1; platform_system!='Emscripten'",
] ]
[project.optional-dependencies] [project.optional-dependencies]