mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-07-28 04:07:46 +00:00
examples/ev3/bluetooth: remove 3rd party dependency
Since Python 3.10, RFCOMM sockets are available in Python on Windows so we no longer need 3rd party code. Fixes: pybricks/support#902
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
from pybricks.messaging import BluetoothMailboxServer, TextMailbox
|
||||
|
||||
# This demo makes your PC talk to an EV3 over Bluetooth.
|
||||
#
|
||||
# This is identical to the EV3 server example in ../bluetooth_server
|
||||
#
|
||||
# The only difference is that it runs in Python3 on your computer, thanks to
|
||||
# the Python3 implementation of the messaging module that is included here.
|
||||
# As far as the EV3 is concerned, it thinks it just talks to an EV3 client.
|
||||
#
|
||||
# So, the EV3 client example needs no further modifications. The connection
|
||||
# procedure is also the same as documented in the messaging module docs:
|
||||
# https://docs.pybricks.com/en/latest/messaging.html
|
||||
|
||||
server = BluetoothMailboxServer()
|
||||
mbox = TextMailbox("greeting", server)
|
||||
|
||||
# The server must be started before the client!
|
||||
print("waiting for connection...")
|
||||
server.wait_for_connection()
|
||||
print("connected!")
|
||||
|
||||
# In this program, the server waits for the client to send the first message
|
||||
# and then sends a reply.
|
||||
mbox.wait()
|
||||
print(mbox.read())
|
||||
mbox.send("hello to you!")
|
||||
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (C) 2020 The Pybricks Authors
|
||||
# Copyright (C) 2020,2023 The Pybricks Authors
|
||||
|
||||
"""
|
||||
:class:`RFCOMMServer` can be used to communicate with other Bluetooth RFCOMM
|
||||
@@ -10,29 +10,13 @@ remain a strict subset of that implementation when it comes to low-level
|
||||
implementation details.
|
||||
"""
|
||||
|
||||
from bluetooth import BluetoothSocket, RFCOMM
|
||||
from socket import socket, AF_BLUETOOTH, BTPROTO_RFCOMM, SOCK_STREAM
|
||||
from socketserver import ThreadingMixIn
|
||||
|
||||
BDADDR_ANY = ""
|
||||
|
||||
|
||||
def str2ba(string, ba):
|
||||
"""Convert string to Bluetooth address"""
|
||||
for i, v in enumerate(string.split(":")):
|
||||
ba.b[5 - i] = int(v, 16)
|
||||
|
||||
|
||||
def ba2str(ba):
|
||||
"""Convert Bluetooth address to string"""
|
||||
string = []
|
||||
for b in ba.b:
|
||||
string.append("{:02X}".format(b))
|
||||
string.reverse()
|
||||
return ":".join(string).upper()
|
||||
|
||||
|
||||
class RFCOMMServer:
|
||||
"""Object that simplifies setting up an RFCOMM socket server.
|
||||
"""
|
||||
Object that simplifies setting up an RFCOMM socket server.
|
||||
|
||||
This is based on the ``socketserver.SocketServer`` class in the Python
|
||||
standard library.
|
||||
@@ -44,10 +28,10 @@ class RFCOMMServer:
|
||||
self.server_address = server_address
|
||||
self.RequestHandlerClass = RequestHandlerClass
|
||||
|
||||
self.socket = BluetoothSocket(RFCOMM)
|
||||
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
|
||||
|
||||
try:
|
||||
self.socket.bind((server_address[0], server_address[1]))
|
||||
self.socket.bind(server_address)
|
||||
# self.server_address = self.socket.getsockname()
|
||||
self.socket.listen(self.request_queue_size)
|
||||
except Exception:
|
||||
@@ -83,50 +67,21 @@ class RFCOMMServer:
|
||||
self.socket.close()
|
||||
|
||||
|
||||
class StreamRequestHandler:
|
||||
"""Class that handles incoming requests.
|
||||
|
||||
This is based on ``socketserver.StreamRequestHandler`` from the Python
|
||||
standard library.
|
||||
"""
|
||||
|
||||
def __init__(self, request, client_address, server):
|
||||
self.request = request
|
||||
self.client_address = client_address
|
||||
self.server = server
|
||||
self.setup()
|
||||
try:
|
||||
self.handle()
|
||||
finally:
|
||||
self.finish()
|
||||
|
||||
def setup(self):
|
||||
self.wfile = self.request
|
||||
self.rfile = self.request
|
||||
|
||||
def handle(self):
|
||||
pass
|
||||
|
||||
def finish(self):
|
||||
pass
|
||||
|
||||
|
||||
class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
|
||||
"""Version of :class:`RFCOMMServer` that handles connections in a new
|
||||
thread.
|
||||
"""
|
||||
|
||||
pass
|
||||
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 = BluetoothSocket(RFCOMM)
|
||||
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
|
||||
|
||||
def handle_request(self):
|
||||
self.socket.connect((self.client_address[0], self.client_address[1]))
|
||||
self.socket.connect(self.client_address)
|
||||
try:
|
||||
self.process_request(self.socket, self.client_address)
|
||||
except Exception:
|
||||
@@ -145,4 +100,7 @@ class RFCOMMClient:
|
||||
|
||||
|
||||
class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient):
|
||||
pass
|
||||
"""
|
||||
Version of :class:`RFCOMMClient` that handles connections in a new thread.
|
||||
"""
|
||||
daemon_threads = True
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (C) 2020 The Pybricks Authors
|
||||
# Copyright (C) 2020,2023 The Pybricks Authors
|
||||
|
||||
from _thread import allocate_lock
|
||||
from errno import ECONNRESET
|
||||
from struct import pack, unpack
|
||||
from socket import BDADDR_ANY
|
||||
from socketserver import StreamRequestHandler
|
||||
from threading import Lock
|
||||
|
||||
from .bluetooth import (
|
||||
BDADDR_ANY,
|
||||
ThreadingRFCOMMServer,
|
||||
ThreadingRFCOMMClient,
|
||||
StreamRequestHandler,
|
||||
)
|
||||
from .bluetooth import ThreadingRFCOMMServer, ThreadingRFCOMMClient
|
||||
|
||||
|
||||
def resolve(brick):
|
||||
@@ -151,7 +148,7 @@ class MailboxHandler(StreamRequestHandler):
|
||||
self.server._clients[self.client_address[0]] = self.request
|
||||
while True:
|
||||
try:
|
||||
buf = self.rfile.recv(2)
|
||||
buf = self.rfile.read(2)
|
||||
if len(buf) == 0:
|
||||
break
|
||||
except OSError as ex:
|
||||
@@ -160,7 +157,7 @@ class MailboxHandler(StreamRequestHandler):
|
||||
break
|
||||
raise
|
||||
(size,) = unpack("<H", buf)
|
||||
buf = self.rfile.recv(size)
|
||||
buf = self.rfile.read(size)
|
||||
msg_count, cmd_type, cmd, name_size = unpack("<HBBB", buf[0:5])
|
||||
if cmd_type != SYSTEM_COMMAND_NO_REPLY:
|
||||
raise ValueError("Bad message type")
|
||||
@@ -180,7 +177,7 @@ class MailboxHandler(StreamRequestHandler):
|
||||
class MailboxHandlerMixIn:
|
||||
def __init__(self):
|
||||
# protects against concurrent access of other attributes
|
||||
self._lock = allocate_lock()
|
||||
self._lock = Lock()
|
||||
# map of mailbox name to raw data
|
||||
self._mailboxes = {}
|
||||
# map of device name/address to object with send() method
|
||||
@@ -247,7 +244,7 @@ class MailboxHandlerMixIn:
|
||||
|
||||
def wait_for_mailbox_update(self, mbox):
|
||||
"""Waits until ``mbox`` receives a value."""
|
||||
lock = allocate_lock()
|
||||
lock = Lock()
|
||||
lock.acquire()
|
||||
with self._lock:
|
||||
self._updates[mbox] = lock
|
||||
|
||||
Reference in New Issue
Block a user