mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-07-28 04:07:46 +00:00
pybricks.pupdevices: Document MarioHub, TechnicMoveHub and DuploTrain.
This commit is contained in:
@@ -18,7 +18,9 @@ FEATURES_MEDIUM = FEATURES_SMALL | {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Large feature set.
|
# Large feature set.
|
||||||
FEATURES_LARGE = FEATURES_MEDIUM | set()
|
FEATURES_LARGE = FEATURES_MEDIUM | {
|
||||||
|
"ble-extra", # Extra features such as pairing or multiple connections.
|
||||||
|
}
|
||||||
|
|
||||||
# Features per hub.
|
# Features per hub.
|
||||||
HUB_FEATURES = {
|
HUB_FEATURES = {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
Duplo Train
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. autoclass:: pybricks.pupdevices.DuploTrain
|
||||||
|
:no-members:
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.connect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.disconnect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.name
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.drive
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.headlights
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.sound
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.speed
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::DuploTrain.color
|
||||||
@@ -22,6 +22,9 @@
|
|||||||
colorlightmatrix
|
colorlightmatrix
|
||||||
light
|
light
|
||||||
remote
|
remote
|
||||||
|
technicmovehub
|
||||||
|
mariohub
|
||||||
|
duplotrain
|
||||||
|
|
||||||
.. pybricks-classlink:: DCMotor
|
.. pybricks-classlink:: DCMotor
|
||||||
|
|
||||||
@@ -94,3 +97,15 @@
|
|||||||
.. figure:: ../../main/cad/output/pupdevice-remote.png
|
.. figure:: ../../main/cad/output/pupdevice-remote.png
|
||||||
:width: 50 %
|
:width: 50 %
|
||||||
:target: remote.html
|
:target: remote.html
|
||||||
|
|
||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
.. pybricks-classlink:: TechnicMoveHub
|
||||||
|
|
||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
.. pybricks-classlink:: MarioHub
|
||||||
|
|
||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
.. pybricks-classlink:: DuploTrain
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
Mario Hub
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
.. autoclass:: pybricks.pupdevices.MarioHub
|
||||||
|
:no-members:
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::MarioHub.connect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::MarioHub.disconnect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::MarioHub.color
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::MarioHub.hsv
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::MarioHub.detectable_colors
|
||||||
@@ -13,6 +13,8 @@ Remote Control
|
|||||||
.. autoclass:: pybricks.pupdevices.Remote
|
.. autoclass:: pybricks.pupdevices.Remote
|
||||||
:no-members:
|
:no-members:
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::Remote.connect
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices::Remote.name
|
.. automethod:: pybricks.pupdevices::Remote.name
|
||||||
|
|
||||||
.. blockimg:: pybricks_blockLightOnColor_remote_on
|
.. blockimg:: pybricks_blockLightOnColor_remote_on
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.. pybricks-requirements:: pybricks-iodevices ble-extra
|
||||||
|
|
||||||
|
Technic Move Hub
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. autoclass:: pybricks.pupdevices.TechnicMoveHub
|
||||||
|
:no-members:
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::TechnicMoveHub.connect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::TechnicMoveHub.disconnect
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices::TechnicMoveHub.drive
|
||||||
@@ -136,12 +136,15 @@ def test_from_pybricks_pupdevices_import():
|
|||||||
"ColorLightMatrix",
|
"ColorLightMatrix",
|
||||||
"ColorSensor",
|
"ColorSensor",
|
||||||
"DCMotor",
|
"DCMotor",
|
||||||
|
"DuploTrain",
|
||||||
"ForceSensor",
|
"ForceSensor",
|
||||||
"InfraredSensor",
|
"InfraredSensor",
|
||||||
"Light",
|
"Light",
|
||||||
|
"MarioHub",
|
||||||
"Motor",
|
"Motor",
|
||||||
"PFMotor",
|
"PFMotor",
|
||||||
"Remote",
|
"Remote",
|
||||||
|
"TechnicMoveHub",
|
||||||
"TiltSensor",
|
"TiltSensor",
|
||||||
"UltrasonicSensor",
|
"UltrasonicSensor",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ CONSTRUCTOR_PARAMS = [
|
|||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.pupdevices",
|
"pybricks.pupdevices",
|
||||||
"Remote",
|
"Remote",
|
||||||
[["name: Optional[str]=None", "timeout: int=10000"]],
|
[["name: Optional[str]=None", "timeout: int=10000", "connect: bool=True"]],
|
||||||
),
|
),
|
||||||
# TODO: iodevices go here
|
# TODO: iodevices go here
|
||||||
pytest.param(
|
pytest.param(
|
||||||
@@ -933,7 +933,7 @@ METHOD_PARAMS = [
|
|||||||
"pybricks.pupdevices",
|
"pybricks.pupdevices",
|
||||||
"Remote",
|
"Remote",
|
||||||
"name",
|
"name",
|
||||||
[(["name: str"], "None"), ([], "str")],
|
[(["name: str"], "MaybeAwaitable"), ([], "str")],
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.pupdevices",
|
"pybricks.pupdevices",
|
||||||
|
|||||||
@@ -435,8 +435,11 @@ class LWP3Device:
|
|||||||
def connect(self) -> MaybeAwaitable:
|
def connect(self) -> MaybeAwaitable:
|
||||||
"""connect()
|
"""connect()
|
||||||
|
|
||||||
Connects to the remote LWP3Device. Only needed if you initialized the
|
Connects to the device. Only needed if you disconnected or initialized
|
||||||
device with ``connect=False``.
|
with ``connect=False``.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the connection attempt fails or times out.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@@ -454,6 +457,9 @@ class LWP3Device:
|
|||||||
Arguments:
|
Arguments:
|
||||||
name (str): New Bluetooth name of the device. If no name is given,
|
name (str): New Bluetooth name of the device. If no name is given,
|
||||||
this method returns the current name.
|
this method returns the current name.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the device is not connected.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def write(self, buf: bytes) -> MaybeAwaitable:
|
def write(self, buf: bytes) -> MaybeAwaitable:
|
||||||
@@ -462,7 +468,11 @@ class LWP3Device:
|
|||||||
Sends a message to the remote hub.
|
Sends a message to the remote hub.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
buf (bytes): The raw binary message to send.
|
buf (bytes): The raw binary message to send. Maximum 20 bytes.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the message exceeds 20 bytes.
|
||||||
|
OSError: If the device is not connected or the write fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def read(self) -> bytes | None:
|
def read(self) -> bytes | None:
|
||||||
@@ -484,7 +494,10 @@ class LWP3Device:
|
|||||||
def disconnect(self) -> MaybeAwaitable:
|
def disconnect(self) -> MaybeAwaitable:
|
||||||
"""disconnect()
|
"""disconnect()
|
||||||
|
|
||||||
Disconnects the remote LWP3Device from the hub.
|
Disconnects the device.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If disconnecting fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+221
-23
@@ -5,9 +5,10 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Collection, Optional, Union, overload
|
from typing import TYPE_CHECKING, Collection, Optional, Union
|
||||||
|
|
||||||
from . import _common
|
from . import _common
|
||||||
|
from .iodevices import LWP3Device
|
||||||
from .parameters import Button, Color, Direction
|
from .parameters import Button, Color, Direction
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -98,7 +99,7 @@ class Motor(_common.Motor):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Remote:
|
class Remote(LWP3Device):
|
||||||
"""LEGO® Powered Up Bluetooth Remote Control."""
|
"""LEGO® Powered Up Bluetooth Remote Control."""
|
||||||
|
|
||||||
light = _common.ExternalColorLight()
|
light = _common.ExternalColorLight()
|
||||||
@@ -115,42 +116,238 @@ class Remote:
|
|||||||
)
|
)
|
||||||
address: Union[str, None]
|
address: Union[str, None]
|
||||||
|
|
||||||
def __init__(self, name: Optional[str] = None, timeout: int = 10000):
|
def __init__(
|
||||||
"""Remote(name=None, timeout=10000)
|
self,
|
||||||
|
name: Optional[str] = None,
|
||||||
When you instantiate this class, the hub will search for a remote
|
timeout: int = 10000,
|
||||||
and connect automatically.
|
connect: bool = True,
|
||||||
|
):
|
||||||
The remote must be on and ready for a connection, as indicated by a
|
"""Remote(name=None, timeout=10000, connect=True)
|
||||||
white blinking light.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
name (str): Bluetooth name of the remote. If no name is given,
|
name (str): Bluetooth name of the remote. If no name is given,
|
||||||
the hub connects to the first remote that it finds.
|
the hub connects to the first remote that it finds.
|
||||||
timeout (Number, ms): How long to search for the remote.
|
timeout (Number, ms): How long to search for the remote.
|
||||||
|
Choose ``None`` to wait indefinitely.
|
||||||
|
connect (bool): Choose ``False`` to skip connecting.
|
||||||
|
``connect()`` can be called later to connect.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the connection attempt fails or times out.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
|
||||||
def name(self, name: str) -> None: ...
|
|
||||||
|
|
||||||
@overload
|
class TechnicMoveHub(LWP3Device):
|
||||||
def name(self) -> str: ...
|
"""LEGO® Technic Move Hub (set 42176, 42214, 42239).
|
||||||
|
|
||||||
def name(self, *args):
|
This newer hub is found in the latest Technic Control+ sets. It requires
|
||||||
"""name(name)
|
a special password to update the firmware, so Pybricks cannot be installed
|
||||||
name() -> str
|
on it. However, you can connect a supported hub running Pybricks to it
|
||||||
|
and control its motors that way.
|
||||||
|
"""
|
||||||
|
|
||||||
Sets or gets the Bluetooth name of the remote.
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
timeout: int = 10000,
|
||||||
|
connect: bool = True,
|
||||||
|
):
|
||||||
|
"""TechnicMoveHub(name=None, timeout=10000, connect=True)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
name (str): New Bluetooth name of the remote. If no name is given,
|
name (str): Bluetooth name of the hub. If no name is given,
|
||||||
this method returns the current name.
|
the hub connects to the first Technic Move Hub it finds.
|
||||||
|
timeout (Number, ms): How long to search for the hub.
|
||||||
|
Choose ``None`` to wait indefinitely.
|
||||||
|
connect (bool): Choose ``False`` to skip connecting.
|
||||||
|
``connect()`` can be called later to connect.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the connection attempt fails or times out.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def disconnect(self) -> MaybeAwaitable:
|
def drive(self, speed: int, steering: int) -> MaybeAwaitable:
|
||||||
"""disconnect()
|
"""drive(speed, steering)
|
||||||
|
|
||||||
Disconnects the remote from the hub.
|
Drives the hub's motor outputs at the given speed and steering.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
speed (int): Drive speed as a percentage (-100 to 100).
|
||||||
|
steering (int): Steering as a percentage (-100 to 100). Positive
|
||||||
|
values steer right. Values exceeding ±97 are clamped to ±97
|
||||||
|
to avoid pushing against the mechanical constraint.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MarioHub(LWP3Device):
|
||||||
|
"""LEGO® Super Mario hub (sets 71360, 71387, 71441 and similar).
|
||||||
|
|
||||||
|
Connect a supported hub running Pybricks to a LEGO Mario, Luigi, or Peach
|
||||||
|
figure and reads its color sensor.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
timeout: int = 10000,
|
||||||
|
connect: bool = True,
|
||||||
|
):
|
||||||
|
"""MarioHub(name=None, timeout=10000, connect=True)
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name (str): Bluetooth name of the hub. If no name is given,
|
||||||
|
the hub connects to the first Mario hub it finds.
|
||||||
|
timeout (Number, ms): How long to search for the hub.
|
||||||
|
Choose ``None`` to wait indefinitely.
|
||||||
|
connect (bool): Choose ``False`` to skip connecting.
|
||||||
|
``connect()`` can be called later to connect.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the connection attempt fails or times out.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def color(self) -> Color:
|
||||||
|
"""color() -> Color
|
||||||
|
|
||||||
|
Reads the color detected by the color sensor from the latest received
|
||||||
|
notification.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Detected color.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def hsv(self) -> Color:
|
||||||
|
"""hsv() -> Color
|
||||||
|
|
||||||
|
Reads the hue, saturation, and brightness of the color detected by the
|
||||||
|
color sensor from the latest received notification, as a
|
||||||
|
:class:`Color <.parameters.Color>` object.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Measured color.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def detectable_colors(self, colors: Collection[Color] = None) -> None:
|
||||||
|
"""detectable_colors(colors)
|
||||||
|
|
||||||
|
Configures the list of colors that :meth:`color` may return.
|
||||||
|
|
||||||
|
Only the colors in this list will be returned. This helps reduce
|
||||||
|
false positives when you only care about a specific subset of colors.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
colors (list): List of :class:`Color <.parameters.Color>` objects
|
||||||
|
to detect, or ``None`` to restore the default list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class DuploTrain(LWP3Device):
|
||||||
|
"""LEGO® Duplo Train hub (sets 10874, 10875, 10427, 10428 similar).
|
||||||
|
|
||||||
|
The Duplo Hub cannot be updated, so you cannot install Pybricks on it.
|
||||||
|
However, you can connect a supported hub running Pybricks to the Duplo Hub
|
||||||
|
and control the train that way.
|
||||||
|
|
||||||
|
You can you control the motor, sound, and headlights, and read the speed
|
||||||
|
and color sensors.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
timeout: int = 10000,
|
||||||
|
connect: bool = True,
|
||||||
|
):
|
||||||
|
"""DuploTrain(name=None, timeout=10000, connect=True)
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name (str): Bluetooth name of the hub. If no name is given,
|
||||||
|
the hub connects to the first Duplo Train hub it finds.
|
||||||
|
timeout (Number, ms): How long to search for the hub.
|
||||||
|
Choose ``None`` to wait indefinitely.
|
||||||
|
connect (bool): Choose ``False`` to skip connecting.
|
||||||
|
``connect()`` can be called later to connect.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the connection attempt fails or times out.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def drive(self, speed: int) -> MaybeAwaitable:
|
||||||
|
"""drive(speed)
|
||||||
|
|
||||||
|
Drives the train motor at the given speed.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
speed (int): Speed as a percentage (-100 to 100). Negative values
|
||||||
|
drive in reverse.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def headlights(self, color: Color) -> MaybeAwaitable:
|
||||||
|
"""headlights(color)
|
||||||
|
|
||||||
|
Sets the color of the train headlights. Not all colors are supported,
|
||||||
|
so the hub will choose the closest color it can produce.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
color (Color): Color of the headlights.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def sound(self, sound: str) -> MaybeAwaitable:
|
||||||
|
"""sound(sound)
|
||||||
|
|
||||||
|
Plays one of the built-in train sounds.
|
||||||
|
|
||||||
|
For the newer (dark blue) train, we have not yet figured out the right
|
||||||
|
sound codes. Please open a discussion or pull request if you know how
|
||||||
|
to do it. Thanks!
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
sound (str): Name of the sound to play. Choose from
|
||||||
|
``"brake"``, ``"depart"``, ``"water"``, ``"horn"``,
|
||||||
|
or ``"steam"``.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def speed(self) -> int:
|
||||||
|
"""speed() -> int: %
|
||||||
|
|
||||||
|
Reads the train speed from the latest received notification.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Speed as a percentage (-100 to 100).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def color(self) -> Color:
|
||||||
|
"""color() -> Color
|
||||||
|
|
||||||
|
Reads the color detected by the color sensor from the latest received
|
||||||
|
notification.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Detected color.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If the hub is not connected.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -461,6 +658,7 @@ if TYPE_CHECKING:
|
|||||||
del Button
|
del Button
|
||||||
del Color
|
del Color
|
||||||
del Direction
|
del Direction
|
||||||
|
del LWP3Device
|
||||||
del MaybeAwaitable
|
del MaybeAwaitable
|
||||||
del MaybeAwaitableBool
|
del MaybeAwaitableBool
|
||||||
del MaybeAwaitableFloat
|
del MaybeAwaitableFloat
|
||||||
|
|||||||
Reference in New Issue
Block a user