Files
pybricks-api/examples/ev3/bluetooth_pc/pybricks/bluetooth.py
T
David Lechner 8e5891d9e8 all: spelling
Misc spelling fixes.
2023-05-10 14:16:15 -05:00

109 lines
3.0 KiB
Python

# SPDX-License-Identifier: MIT
# Copyright (C) 2020,2023 The Pybricks Authors
"""
:class:`RFCOMMServer` can be used to communicate with other Bluetooth RFCOMM
devices that don't support the EV3 mailbox protocol.
It is based on the standard library ``socketserver`` module and attempts to
remain a strict subset of that implementation when it comes to low-level
implementation details.
"""
from socket import socket, AF_BLUETOOTH, BTPROTO_RFCOMM, SOCK_STREAM
from socketserver import ThreadingMixIn
class RFCOMMServer:
"""
Object that simplifies setting up an RFCOMM socket server.
This is based on the ``socketserver.SocketServer`` class in the Python
standard library.
"""
request_queue_size = 1
def __init__(self, server_address, RequestHandlerClass):
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
try:
self.socket.bind(server_address)
# self.server_address = self.socket.getsockname()
self.socket.listen(self.request_queue_size)
except Exception:
self.server_close()
raise
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.server_close()
def handle_request(self):
try:
request, addr_data = self.socket.accept()
except OSError:
return
try:
self.process_request(request, addr_data)
except Exception:
request.close()
raise
def process_request(self, request, client_address):
self.finish_request(request, client_address)
request.close()
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
def server_close(self):
self.socket.close()
class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
"""
Version of :class:`RFCOMMServer` that handles connections in a new thread.
"""
daemon_threads = True
class RFCOMMClient:
def __init__(self, client_address, RequestHandlerClass):
self.client_address = client_address
self.RequestHandlerClass = RequestHandlerClass
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
def handle_request(self):
self.socket.connect(self.client_address)
try:
self.process_request(self.socket, self.client_address)
except Exception:
self.socket.close()
raise
def process_request(self, request, client_address):
self.finish_request(request, client_address)
request.close()
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
def client_close(self):
self.socket.close()
class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient):
"""
Version of :class:`RFCOMMClient` that handles connections in a new thread.
"""
daemon_threads = True