Compare commits

...
Author SHA1 Message Date
Laurens Valk c78eb16660 v4.0.0b2 2026-05-29 21:35:04 +02:00
Laurens Valk fa7a336fd1 .github/workflows: Use trusted publishing. 2026-05-29 21:34:14 +02:00
Laurens Valk d5f6a1ad00 v4.0.0b1 2026-05-29 21:15:09 +02:00
Laurens Valk 5bef252078 .github/workflows: Build on v4 tags. 2026-05-29 21:15:03 +02:00
Laurens Valk f12a6a26ac .github/workflows: Convert python to npm semver style. 2026-05-29 21:06:31 +02:00
Laurens Valk 4e78de9d2a .github/workflows: Update actions. 2026-05-29 20:57:04 +02:00
Laurens Valk 95b168355e npm: Simplify release pipeline.
Releasing API updates is quite a long and error prone process, so the point that it was limiting our ability to push frequent updates in practice. There were 5 tag, commit, wait, and proceed steps and you'd have to start over or force push if a mistake was made.

This keeps all the npm packages as they were, but versions everything from a single source of truth, which is this project's main version. Everything builds on a tag on the main repo, much like we did for a regular IDE docs RTD release.

It also skips the PyPI for jedi as an intermediate step, which isn't really needed and required us to have this strict order of publication steps.
2026-05-29 20:38:37 +02:00
Laurens Valk a9be86238d pybricks.messaging.BLERadio: Fix example paths. 2026-05-29 20:28:36 +02:00
Laurens Valk 16d5ba64d2 pybricks.ev3devices: Update return types. 2026-05-29 20:09:06 +02:00
Laurens Valk d8802ace7d pybricks.common: Update system info. 2026-05-29 20:08:53 +02:00
Laurens Valk acb5206349 pybricks.robotics: Update DriveBase. 2026-05-29 20:06:56 +02:00
Laurens Valk 6686fce3c3 pybricks.pupdevices: Document MarioHub, TechnicMoveHub and DuploTrain. 2026-05-29 16:59:51 +02:00
Laurens Valk 7d27fbb5d8 pybricks.iodevices: Document DCMotor. 2026-05-29 15:39:24 +02:00
Laurens Valk a0e98ba75f pybricks.iodevices: Document pinout. 2026-05-29 15:34:58 +02:00
Laurens Valk 1b69e42b6b pybricks.iodevices: Update UARTDevice docstrings. 2026-05-29 14:57:53 +02:00
Laurens Valk 47a3d664c2 pybricks.iodevices: Include all classes in index.
Some were omitted once EV3 in Pybricks 2.0 was dropped, but they will be included again to prepare for EV3 in Pybricks 4.0.

Enable for Powered UP where relevant, as with UARTDevice.
2026-05-29 14:22:15 +02:00
Laurens Valk e6cb436c47 pybricks.iodevices: Update I2CDevice docstrings. 2026-05-29 13:41:10 +02:00
Laurens Valk a8d74720b6 pybricks.iodevices: Update AnalogSensor docstrings. 2026-05-29 12:38:49 +02:00
Laurens Valk 54b4e39360 pybricks.iodevices: Update XboxController docstrings. 2026-05-29 12:32:43 +02:00
Laurens Valk 1f8f0f777a pybricks.iodevices: Update PUPDevice and LUMPDevice.
Also remove Ev3devSensor, which is no longer used.
2026-05-29 12:30:58 +02:00
Laurens Valk 45b9b89d11 pybricks.messaging: Add tests. 2026-05-29 11:48:15 +02:00
Laurens Valk e0f48b178b pybricks.messaging: Document AppData. 2026-05-29 11:41:45 +02:00
Laurens Valk 8ed5a489b9 pybricks.messaging.BLERadio: Include raised errors. 2026-05-29 11:24:41 +02:00
Laurens Valk a2ba8e4dcd pybricks.hubs: Move .ble to BLERadio.
Follows upstream firmware change.

Update tests and examples too.
2026-05-29 11:12:50 +02:00
Frederik Leonhardt 7900f03574 jedi: Add tests for methods on hub.ble. 2026-05-28 11:20:54 +02:00
Frederik Leonhardt 7014f46441 pybricks.common.BLE: Improve typing for broadcast() and observe()
- Add overloads for broadcast(). It accepts either a single value, or a tuple,
  or a list.

- Adjust return type of observe(). It either returns a single value, or a tuple.
2026-05-28 11:12:17 +02:00
Frederik Leonhardt 7411a246c9 pybricks.common.BLE: Improve typing for hub constructor.
Update type hint for broadcast_channel to Optional, as None is allowed.
2026-05-28 11:12:17 +02:00
Lasse Deleuran 3bc2f35e3e pybricks.iodevices: Added missing functions and parameters.
* Added missing functions and parameters to documentation.

- AnalogSensor: Missing parameter "custom".
- I2CDevice: Missing parameters "port", "address", "custom", "powered", and "nxt_quirk" with attempted explanation of parameters.
- UARTDevice: Missing default parameter value.
- LWP3Device: Missing "connect" parameter.
- Added missing connect and disconnnect methods.
- XboxController: Missing documentation in constructor and missing methods.

* Minor changes to the documentation

Made it more clear and less verbose when to skip connect to bluetooth devices.
2026-05-28 10:47:04 +02:00
kai-morich 61578b5547 pybricks.parameters: Add/fix operators for Color type.
* Implement `Color.__eq__`, fix `Color.__mul__`. This allows testing of color block sorting algorithms with CPython.
* implement `Color.__lshift__` and immutability for completeness.
2026-04-25 11:01:54 -05:00
JoBe c615ccf986 pybricks._common: Fix parameter name in LightMatrix.orientation().
The parameter `up` was named `top` here, which does not reflect the state of the current code.

See https://github.com/pybricks/pybricks-micropython/blob/master/pybricks/common/pb_type_lightmatrix.c#L59C25 for usage in the code itself.
2026-03-29 17:41:34 -05:00
Gabriel Couchenour 32f974e7e5 Robotics.py: Fix issue with the type stub for DriveBase.angle() (#165)
The type was changed from `int` to `float` in https://github.com/pybricks/pybricks-micropython/commit/4d457a17fc13d42d9b311df99e05dafaeed67862.

Technically, it is still `int` on BOOST Move hub (any system without floating point support). But most platforms use `float` so makes sense to have that in the type hints.
2025-09-19 21:53:37 -05:00
Laurens Valk 0efcfd4a36 pybricks.iodevices.LWP3Device: Document new parameters. 2025-06-16 11:05:13 +02:00
Laurens Valk 356f6ffdba v3.6.1 2025-05-01 11:30:32 +02:00
Laurens Valk 4967b96ddd doc/main: Fix trailing whitespace.
For some reason this was not caught by CI.
2025-05-01 11:27:33 +02:00
Laurens Valk 116368e4c7 pybricks.hubs: List missing system.info method. 2025-05-01 11:25:56 +02:00
Laurens Valk 5b56249d8c doc/common/extensions: Drop unused imports. 2025-05-01 11:19:48 +02:00
Laurens Valk 04fb7e3e19 @pybricks/images/v1.4.0 2025-03-19 10:33:59 +01:00
Laurens Valk 5814a73bb1 v3.6.0 2025-03-11 13:08:17 +01:00
Laurens Valk ed3059b47b pybricks.common.IMU: Clarify notes on calibrated values. 2025-03-11 13:01:10 +01:00
Laurens Valk 2a98264144 @pybricks/jedi/v1.17.0 2025-02-26 12:54:14 +01:00
Laurens Valk 6083b17d9a pybricks_jedi/v1.17.0 2025-02-26 12:49:04 +01:00
Laurens Valk 1c598f35be @pybricks/ide-docs/v2.20.0 2025-02-26 12:33:03 +01:00
Laurens Valk 52c522df2d v3.6.0b5 2025-02-26 12:29:10 +01:00
Laurens Valk 2380be2814 extensions/blockimg: Embed svg.
This cuts the total build from 527 to 156 files,
which is considerably fewer requests when loading
this inside Pybricks Code.

See https://github.com/pybricks/support/issues/1559
2025-02-26 10:58:03 +01:00
Laurens Valk 89a34e9f51 conf: Don't export txt sources.
The sources are hosted on GitHub, so there is not additional information here. Also, the actual docstrings are included in the .py files.

See https://github.com/pybricks/support/issues/1559
2025-02-26 10:17:08 +01:00
Laurens Valk 9597f227f4 pybricks.common.IMU: Add settings blocks. 2025-02-25 13:47:07 +01:00
Laurens Valk 1e09cb2232 builtins: Document missing eval and exec on Move Hub.
Fixes https://github.com/pybricks/support/issues/1931
2025-02-25 11:32:01 +01:00
Laurens Valk 6739b517a5 examples: Fix duty cycle comment.
Fixes https://github.com/pybricks/support/issues/2029
2025-02-25 11:26:16 +01:00
Laurens Valk c5cfcd0ac8 tests: Update for IMU changes. 2025-02-25 11:16:27 +01:00
Laurens Valk 827eda031b pybricks.common.System: Document new system info. 2025-02-25 11:16:27 +01:00
Laurens Valk c77b440270 pybricks.parameters: Allow iterating colors.
https://github.com/pybricks/support/issues/1661
2025-02-25 11:16:27 +01:00
Laurens Valk 789e70a42b pybricks.common.BLE: Broadcast fixes.
Fix missing awaitable. Fix default broadcast channel following firmware update.
2025-02-25 11:16:27 +01:00
Laurens Valk 53d6d14de6 pybricks.common.IMU: Document calibration kwarg option. 2025-02-25 11:16:27 +01:00
Laurens Valk ce9d7420fb pybricks.common.IMU: Document new settings.
Also dcument hub.system.reset_storage.
2025-02-25 11:16:27 +01:00
Laurens Valk 044903b193 pybricks.common.Motor: Clarify drive base reset side effect.
Fixes https://github.com/pybricks/support/issues/1449
2025-02-25 11:16:27 +01:00
Laurens Valk 25bfd0e80e pybricks.robotics.DriveBase: Document curve and reset updates. 2025-02-25 11:16:27 +01:00
David Lechner b28f768bec pybricks.lwp3device: Show compatibility.
It has come up a few times recently that this wasn't clear.
2025-01-25 11:02:54 -06:00
Laurens Valk f35bbe44f5 @pybricks/ide-docs/v2.19.0 2024-04-11 14:36:16 +02:00
Laurens Valk 08fa5b1c17 v3.5.0 2024-04-11 14:34:22 +02:00
Laurens Valk 6982cf4fd2 @pybricks/jedi/v1.16.0 2024-04-05 11:47:00 +02:00
Laurens Valk 8ffdde38e6 pybricks_jedi/v1.16.0 2024-04-05 11:45:50 +02:00
97 changed files with 16073 additions and 1182 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
+1 -16
View File
@@ -7,24 +7,9 @@ jobs:
if: github.ref_type != 'tag'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- run: pipx install poetry
- run: poetry install
working-directory: ./jedi
- run: poetry run pytest -vv
working-directory: ./jedi
publish:
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'pybricks_jedi/')
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- run: pipx install poetry
- run: poetry install
working-directory: ./jedi
- run: poetry build
working-directory: ./jedi
- run: poetry publish
working-directory: ./jedi
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_PYBRICKS_JEDI_TOKEN }}
+17 -9
View File
@@ -2,22 +2,30 @@ name: Release @pybricks/ide-docs
on:
push:
tags:
- '@pybricks/ide-docs/**'
tags:
- 'v4.*'
jobs:
publish_ide_docs:
runs-on: ubuntu-22.04
permissions:
id-token: write
steps:
- name: Get version from tag
run: |
VERSION="${GITHUB_REF_NAME#v}"
NPM_VERSION=$(echo "$VERSION" | sed 's/\([0-9]\)a\([0-9]\)/\1-alpha.\2/;s/\([0-9]\)b\([0-9]\)/\1-beta.\2/;s/\([0-9]\)rc\([0-9]\)/\1-rc.\2/')
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_ENV
- name: Ubuntu packages
run: |
sudo apt-get update
sudo apt-get install -y dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Install dependencies
@@ -26,13 +34,13 @@ jobs:
poetry run python -m pip install --upgrade pip
poetry run python -m pip install --upgrade setuptools
poetry install --only=doc
- uses: actions/setup-node@v3
- uses: actions/setup-node@v6
with:
node-version: '14.x'
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: npm version --no-git-tag-version "$NPM_VERSION"
working-directory: npm/ide-docs
- run: yarn build
working-directory: npm/ide-docs
- run: yarn publish
- run: npm publish
working-directory: npm/ide-docs
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
+3 -3
View File
@@ -9,11 +9,11 @@ jobs:
publish_ide_docs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: ./build.py
working-directory: npm/images
+24 -10
View File
@@ -2,22 +2,36 @@ name: Release @pybricks/jedi
on:
push:
tags:
- '@pybricks/jedi/**'
tags:
- 'v4.*'
jobs:
publish_jedi:
runs-on: ubuntu-22.04
permissions:
id-token: write
steps:
- uses: actions/checkout@v3
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- name: Get version from tag
run: |
VERSION="${GITHUB_REF_NAME#v}"
NPM_VERSION=$(echo "$VERSION" | sed 's/\([0-9]\)a\([0-9]\)/\1-alpha.\2/;s/\([0-9]\)b\([0-9]\)/\1-beta.\2/;s/\([0-9]\)rc\([0-9]\)/\1-rc.\2/')
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_ENV
- name: Set up Python
uses: actions/setup-python@v5
with:
node-version: '16.x'
python-version: '3.11'
- name: Install poetry
run: pipx install poetry
- name: Set pybricks-jedi version
run: poetry version "$VERSION"
working-directory: jedi
- uses: actions/setup-node@v6
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: ./build.py
- run: ./build.py "$NPM_VERSION"
working-directory: npm/jedi
- run: yarn publish
- run: npm publish
working-directory: npm/jedi/build
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
+3 -3
View File
@@ -1,7 +1,7 @@
on:
push:
tags:
- 'v3.*'
- 'v4.*'
name: Create release on GitHub and PyPI
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v6
with:
submodules: true
fetch-depth: 0
@@ -38,7 +38,7 @@ jobs:
build_and_publish:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- run: pipx run poetry build
- run: pipx run poetry publish
env:
-1
View File
@@ -24,7 +24,6 @@ EV3
ev3brick
ev3dev
ev3devices
Ev3devSensor
fb
Franca
func
+41
View File
@@ -4,6 +4,47 @@
## Unreleased
## 4.0.0b2 - 2026-05-29
### Changed
- Change NPM publishing to trusted publishers.
## 4.0.0b1 - 2026-05-29
### Changed
- Updated API for firmware 4.0.0bx. See upstream changelog for details.
- Updated release pipeline to publish rtd, npm/docs and npm/jedi on tag.
### Fixed
- Fixed `DriveBase.angle` reporting an incorrect return type.
## 3.6.1 - 2025-05-01
### Fixed
- Fixed missing `hub.system.info` method on some hubs.
## 3.6.0 - 2025-03-11
### Changed
- Update API for firmware 3.6.0. See upstream changelog for details.
## 3.6.0b5 - 2025-02-26
### Changed
- Update API for firmware 3.6.0b5. See upstream changelog for details.
## 3.5.0 - 2024-04-11
### Changed
- Bump version to 3.5.0 without additional changes.
## 3.5.0b2 - 2024-04-05
### Added
+5
View File
@@ -163,6 +163,11 @@ Linting:
poetry run flake8 # check Python
poetry run doc8 # check Restructured Text
Building all release artifacts (docs, jedi, npm packages):
# Linux/macOS only
./build-all.sh
[vscode]: https://code.visualstudio.com/
[git]: https://git-scm.com/
[python]: https://www.python.org/
Executable
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Build all release artifacts locally (equivalent to CI workflows, minus publish).
set -euo pipefail
REPO_ROOT="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
# Activate the project venv so python/make/etc. all use it without poetry run
source "$REPO_ROOT/.venv/bin/activate"
# Read version from pyproject.toml
VERSION=$(grep '^version = ' "$REPO_ROOT/pyproject.toml" | head -1 | sed 's/version = "\(.*\)"/\1/')
# Convert Python pre-release format (e.g. 4.0.0a1, 4.0.0b1, 4.0.0rc1) to npm semver (e.g. 4.0.0-alpha.1, 4.0.0-beta.1, 4.0.0-rc.1)
NPM_VERSION=$(echo "$VERSION" | sed 's/\([0-9]\)a\([0-9]\)/\1-alpha.\2/;s/\([0-9]\)b\([0-9]\)/\1-beta.\2/;s/\([0-9]\)rc\([0-9]\)/\1-rc.\2/')
echo "==> Building version $VERSION (npm: $NPM_VERSION)"
# lint
echo "==> Linting"
cd "$REPO_ROOT"
flake8
doc8
# pybricks-jedi wheel (from local source)
echo "==> Testing pybricks-jedi"
cd "$REPO_ROOT/jedi"
poetry run pytest -vv
echo "==> Building pybricks-jedi wheel"
cd "$REPO_ROOT/jedi"
rm -rf dist/
poetry build --format=wheel
# @pybricks/jedi npm package
echo "==> Building @pybricks/jedi"
cd "$REPO_ROOT"
python3 npm/jedi/build.py "$NPM_VERSION"
# @pybricks/ide-docs npm package
echo "==> Building @pybricks/ide-docs"
cd "$REPO_ROOT"
make -C doc clean
cd "$REPO_ROOT/npm/ide-docs"
yarn build
echo ""
echo "Build complete."
echo " jedi npm package : npm/jedi/build/"
echo " ide-docs : npm/ide-docs/html/"
+10 -2
View File
@@ -1,3 +1,11 @@
.block-image {
margin-top: 10px;
.svg-container {
display: inline-block;
width: 100%;
height: auto;
}
.svg-container svg {
position: relative;
height: auto;
max-width: 100%;
}
+4 -6
View File
@@ -151,6 +151,9 @@ import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_show_sourcelink = False
html_copy_source = False
html_context = {
"disclaimer": _DISCLAIMER,
}
@@ -251,16 +254,11 @@ latex_documents = [
exclude_patterns = [
"ev3devices.rst",
"hubs/ev3brick.rst",
"iodevices/analogsensor.rst",
"iodevices/dcmotor.rst",
"iodevices/ev3devsensor.rst",
"iodevices/i2cdevice.rst",
"iodevices/lumpdevice.rst",
"iodevices/uartdevice.rst",
"media.rst",
"messaging.rst",
"nxtdevices.rst",
"tools/datalog.rst",
"*.rst.txt",
]
+16 -35
View File
@@ -1,56 +1,37 @@
import xml.etree.ElementTree as ET
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives.images import Image
from docutils.nodes import image, paragraph
from docutils.parsers.rst import Directive
from docutils import nodes
from pathlib import Path
SPHINX_IMAGE_PATH = "blockimg"
SVG_SCALE = 0.9
def get_svg_size(file_path):
tree = ET.parse(file_path)
root = tree.getroot()
width = root.attrib.get("width")
height = root.attrib.get("height")
return float(width), float(height)
def get_svg_content(file_path):
with open(file_path, "r", encoding="utf-8") as file:
return file.read()
# Global variable to store the app object
app = None
class BlockImageDirective(Image):
option_spec = Image.option_spec.copy()
option_spec["stack"] = directives.flag
class BlockImageDirective(Directive):
has_content = False
required_arguments = 1
optional_arguments = 0
def run(self):
# Adjust the image path
file_name = self.arguments[0] + ".svg"
self.arguments[0] = "/" + SPHINX_IMAGE_PATH + "/" + file_name
path = Path(app.srcdir) / SPHINX_IMAGE_PATH / file_name
file_path = Path(app.srcdir) / SPHINX_IMAGE_PATH / file_name
# Set it to the scaled SVG size unless width explicitly set.
if self.options.get("width") is None:
width, height = get_svg_size(path)
self.options["width"] = str(round(width * SVG_SCALE)) + "px"
self.options["height"] = str(round(height * SVG_SCALE)) + "px"
# Read the SVG content
svg_content = get_svg_content(file_path)
# Call the parent class's run method
nodes = super().run()
# Create a raw HTML node with the SVG content
raw_html = f'<div class="svg-container">{svg_content}</div>'
raw_node = nodes.raw("", raw_html, format="html")
# Wrap each image node in a paragraph node
for i, node in enumerate(nodes):
if isinstance(node, image):
if "stack" not in self.options:
node["classes"].append("block-image")
nodes[i] = paragraph("", "", node)
return nodes
return [raw_node]
def setup(apparg):
+17 -9
View File
@@ -18,14 +18,23 @@ FEATURES_MEDIUM = FEATURES_SMALL | {
}
# 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.
HUB_FEATURES = {
"movehub": {"movehub"} | FEATURES_SMALL,
"cityhub": {"cityhub"} | FEATURES_MEDIUM,
"technichub": {"technichub", "gyro", "xbox-controller"} | FEATURES_MEDIUM,
"primehub": {"primehub", "inventorhub", "light-matrix", "gyro", "xbox-controller"}
"movehub": {"movehub", "pup"} | FEATURES_SMALL,
"cityhub": {"cityhub", "pup"} | FEATURES_MEDIUM,
"technichub": {"technichub", "gyro", "xbox-controller", "pup"} | FEATURES_MEDIUM,
"primehub": {
"primehub",
"inventorhub",
"light-matrix",
"gyro",
"xbox-controller",
"pup",
}
| FEATURES_LARGE,
"inventorhub": {
"primehub",
@@ -33,9 +42,10 @@ HUB_FEATURES = {
"light-matrix",
"gyro",
"xbox-controller",
"pup",
}
| FEATURES_LARGE,
"essentialhub": {"essentialhub", "gyro", "xbox-controller"} | FEATURES_LARGE,
"essentialhub": {"essentialhub", "gyro", "xbox-controller", "pup"} | FEATURES_LARGE,
}
@@ -94,9 +104,7 @@ class PybricksRequirementsStaticDirective(Directive):
</tbody>
</table>
</div>
""".format(
compat_row
)
""".format(compat_row)
# Return the node.
node = nodes.raw("", html, format="html")
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

+89
View File
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg2"
width="525"
height="525"
viewBox="0 0 525 525"
sodipodi:docname="icon_ev3hub.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
inkscape:export-filename="../diagrams/icon_ev3hub.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath860">
<rect
style="fill:#6ab0de;fill-opacity:1;stroke:#6ab0de;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862"
width="589.10107"
height="96.333336"
x="235.33333"
y="-236.00002" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1040">
<rect
style="fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1042"
width="128.5101"
height="19.934668"
x="827.15656"
y="74.666672" />
</clipPath>
</defs>
<sodipodi:namedview
pagecolor="#fcfcfc"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1163"
id="namedview4"
showgrid="false"
inkscape:zoom="0.9950413"
inkscape:cx="301.49502"
inkscape:cy="344.70931"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:snap-global="false"
inkscape:pagecheckerboard="0" />
<image
width="525"
height="468.02328"
preserveAspectRatio="none"
xlink:href="../cad/output/ev3device-ev3.png"
id="image834"
x="0"
y="26.384924" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+89
View File
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg2"
width="525"
height="525"
viewBox="0 0 525 525"
sodipodi:docname="icon_nxthub.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
inkscape:export-filename="../diagrams/icon_nxthub.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath860">
<rect
style="fill:#6ab0de;fill-opacity:1;stroke:#6ab0de;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862"
width="589.10107"
height="96.333336"
x="235.33333"
y="-236.00002" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1040">
<rect
style="fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1042"
width="128.5101"
height="19.934668"
x="827.15656"
y="74.666672" />
</clipPath>
</defs>
<sodipodi:namedview
pagecolor="#fcfcfc"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1163"
id="namedview4"
showgrid="false"
inkscape:zoom="0.9950413"
inkscape:cx="301.49502"
inkscape:cy="344.70931"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:snap-global="false"
inkscape:pagecheckerboard="false" />
<image
width="525"
height="447.39801"
preserveAspectRatio="none"
xlink:href="../cad/output/nxtdevice-nxt.png"
id="image960"
x="0"
y="34.809708" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+4 -36
View File
@@ -8,7 +8,6 @@ City Hub
.. blockimg:: pybricks_variables_set_city_hub_option0
.. blockimg:: pybricks_variables_set_city_hub_option3
:stack:
.. autoclass:: pybricks.hubs.CityHub
:no-members:
@@ -27,20 +26,6 @@ City Hub
.. automethod:: pybricks.hubs::CityHub.light.animate
.. rubric:: Using connectionless Bluetooth messaging
.. blockimg:: pybricks_blockBleBroadcast_CityHub
.. automethod:: pybricks.hubs::CityHub.ble.broadcast
.. blockimg:: pybricks_blockBleObserve_CityHub
.. automethod:: pybricks.hubs::CityHub.ble.observe
.. automethod:: pybricks.hubs::CityHub.ble.signal_strength
.. automethod:: pybricks.hubs::CityHub.ble.version
.. rubric:: Using the battery
.. blockimg:: pybricks_blockBatteryMeasure_CityHub_battery.voltage
@@ -57,26 +42,26 @@ City Hub
.. automethod:: pybricks.hubs::CityHub.buttons.pressed
.. automethod:: pybricks.hubs::CityHub.system.info
.. blockimg:: pybricks_blockHubStopButton_CityHub
.. blockimg:: pybricks_blockHubStopButton_CityHub_none
:stack:
.. automethod:: pybricks.hubs::CityHub.system.set_stop_button
.. automethod:: pybricks.hubs::CityHub.system.name
.. automethod:: pybricks.hubs::CityHub.system.storage
You can store up to 128 bytes of data on this hub. The data is cleared
when you update the Pybricks firmware or if you restore the original
firmware.
.. automethod:: pybricks.hubs::CityHub.system.reset_storage
.. blockimg:: pybricks_blockHubShutdown_CityHub
.. automethod:: pybricks.hubs::CityHub.system.shutdown
.. automethod:: pybricks.hubs::CityHub.system.reset_reason
Status light examples
---------------------
@@ -105,23 +90,6 @@ Creating light animations
.. literalinclude::
../../../examples/pup/hub_common/build/light_animate_cityhub.py
Bluetooth examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_broadcast_cityhub.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_cityhub.py
Button and system examples
----------------------------------
+18 -38
View File
@@ -9,7 +9,6 @@ Essential Hub
.. blockimg:: pybricks_variables_set_essential_hub_option0
.. blockimg:: pybricks_variables_set_essential_hub_option4
:stack:
.. autoclass:: pybricks.hubs.EssentialHub
:no-members:
@@ -37,12 +36,18 @@ Essential Hub
.. blockimg:: pybricks_blockHubStopButton_EssentialHub
.. blockimg:: pybricks_blockHubStopButton_EssentialHub_none
:stack:
.. automethod:: pybricks.hubs::EssentialHub.system.set_stop_button
.. rubric:: Using the IMU
.. versionchanged:: 3.6
The methods below now return calibrated data by default. Depending on
the method used, this combines data from the accelerometer, gyroscope,
with your calibration values. Use ``calibrated=False`` where applicable
to get the raw data you got before.
.. blockimg:: pybricks_blockImuStatus_EssentialHub_ready
.. automethod:: pybricks.hubs::EssentialHub.imu.ready
@@ -58,7 +63,6 @@ Essential Hub
.. blockimg:: pybricks_blockTilt_EssentialHub_imu.tilt.pitch
.. blockimg:: pybricks_blockTilt_EssentialHub_imu.tilt.roll
:stack:
.. automethod:: pybricks.hubs::EssentialHub.imu.tilt
@@ -84,22 +88,14 @@ Essential Hub
.. automethod:: pybricks.hubs::EssentialHub.imu.orientation
.. blockimg:: pybricks_blockImuConfigure_EssentialHub_imu.settings_heading_correction
.. blockimg:: pybricks_blockImuConfigure_EssentialHub_imu.settings_angular_velocity_threshold
.. blockimg:: pybricks_blockImuConfigure_EssentialHub_imu.settings_acceleration_threshold
.. automethod:: pybricks.hubs::EssentialHub.imu.settings
.. rubric:: Using connectionless Bluetooth messaging
.. blockimg:: pybricks_blockBleBroadcast_EssentialHub
.. automethod:: pybricks.hubs::EssentialHub.ble.broadcast
.. blockimg:: pybricks_blockBleObserve_EssentialHub
.. automethod:: pybricks.hubs::EssentialHub.ble.observe
.. automethod:: pybricks.hubs::EssentialHub.ble.signal_strength
.. automethod:: pybricks.hubs::EssentialHub.ble.version
.. rubric:: Using the battery
.. blockimg:: pybricks_blockBatteryMeasure_EssentialHub_battery.voltage
@@ -120,18 +116,19 @@ Essential Hub
.. rubric:: System control
.. automethod:: pybricks.hubs::EssentialHub.system.name
.. automethod:: pybricks.hubs::EssentialHub.system.info
.. automethod:: pybricks.hubs::EssentialHub.system.storage
You can store up to 512 bytes of data on this hub.
You can store up to 512 bytes of data on this hub. The data is cleared
when you update the Pybricks firmware.
.. automethod:: pybricks.hubs::EssentialHub.system.reset_storage
.. blockimg:: pybricks_blockHubShutdown_EssentialHub
.. automethod:: pybricks.hubs::EssentialHub.system.shutdown
.. automethod:: pybricks.hubs::EssentialHub.system.reset_reason
Status light examples
---------------------
@@ -193,23 +190,6 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_essentialhub.py
Bluetooth examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_broadcast_essentialhub.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_essentialhub.py
System examples
----------------------------------
+4 -38
View File
@@ -11,7 +11,6 @@ Move Hub
.. blockimg:: pybricks_variables_set_move_hub_option0
.. blockimg:: pybricks_variables_set_move_hub_option4
:stack:
.. autoclass:: pybricks.hubs.MoveHub
:no-members:
@@ -39,7 +38,6 @@ Move Hub
.. blockimg:: pybricks_blockTilt_MoveHub_imu.tilt.pitch
.. blockimg:: pybricks_blockTilt_MoveHub_imu.tilt.roll
:stack:
.. automethod:: pybricks.hubs::MoveHub.imu.tilt
@@ -51,20 +49,6 @@ Move Hub
Changed acceleration units from m/s² to mm/s².
.. rubric:: Using connectionless Bluetooth messaging
.. blockimg:: pybricks_blockBleBroadcast_PrimeHub
.. automethod:: pybricks.hubs::PrimeHub.ble.broadcast
.. blockimg:: pybricks_blockBleObserve_PrimeHub
.. automethod:: pybricks.hubs::PrimeHub.ble.observe
.. automethod:: pybricks.hubs::MoveHub.ble.signal_strength
.. automethod:: pybricks.hubs::MoveHub.ble.version
.. rubric:: Using the battery
.. blockimg:: pybricks_blockBatteryMeasure_MoveHub_battery.voltage
@@ -81,27 +65,26 @@ Move Hub
.. automethod:: pybricks.hubs::MoveHub.buttons.pressed
.. automethod:: pybricks.hubs::MoveHub.system.info
.. blockimg:: pybricks_blockHubStopButton_MoveHub
.. blockimg:: pybricks_blockHubStopButton_MoveHub_none
:stack:
.. automethod:: pybricks.hubs::MoveHub.system.set_stop_button
.. automethod:: pybricks.hubs::MoveHub.system.name
.. automethod:: pybricks.hubs::MoveHub.system.storage
You can store up to 128 bytes of data on this hub. The data is cleared
when you update the Pybricks firmware or if you restore the original
firmware.
.. automethod:: pybricks.hubs::MoveHub.system.reset_storage
.. blockimg:: pybricks_blockHubShutdown_MoveHub
.. automethod:: pybricks.hubs::MoveHub.system.shutdown
.. automethod:: pybricks.hubs::MoveHub.system.reset_reason
Status light examples
---------------------
@@ -132,23 +115,6 @@ Reading acceleration
.. literalinclude::
../../../examples/pup/hub_movehub/imu_read_acceleration.py
Bluetooth examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_broadcast_movehub.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_movehub.py
Button and system examples
----------------------------------
+20 -39
View File
@@ -9,7 +9,6 @@ Prime Hub / Inventor Hub
.. blockimg:: pybricks_variables_set_inventor_hub_option0
.. blockimg:: pybricks_variables_set_inventor_hub_option4
:stack:
.. class:: InventorHub
@@ -21,7 +20,6 @@ Prime Hub / Inventor Hub
.. blockimg:: pybricks_variables_set_prime_hub_option0
.. blockimg:: pybricks_variables_set_prime_hub_option4
:stack:
.. autoclass:: pybricks.hubs.PrimeHub
:no-members:
@@ -84,12 +82,18 @@ Prime Hub / Inventor Hub
.. blockimg:: pybricks_blockHubStopButton_PrimeHub
.. blockimg:: pybricks_blockHubStopButton_PrimeHub_none
:stack:
.. automethod:: pybricks.hubs::PrimeHub.system.set_stop_button
.. rubric:: Using the IMU
.. versionchanged:: 3.6
The methods below now return calibrated data by default. Depending on
the method used, this combines data from the accelerometer, gyroscope,
with your calibration values. Use ``calibrated=False`` where applicable
to get the raw data you got before.
.. blockimg:: pybricks_blockImuStatus_PrimeHub_ready
.. automethod:: pybricks.hubs::PrimeHub.imu.ready
@@ -105,7 +109,6 @@ Prime Hub / Inventor Hub
.. blockimg:: pybricks_blockTilt_PrimeHub_imu.tilt.pitch
.. blockimg:: pybricks_blockTilt_PrimeHub_imu.tilt.roll
:stack:
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
@@ -131,6 +134,12 @@ Prime Hub / Inventor Hub
.. automethod:: pybricks.hubs::PrimeHub.imu.orientation
.. blockimg:: pybricks_blockImuConfigure_PrimeHub_imu.settings_heading_correction
.. blockimg:: pybricks_blockImuConfigure_PrimeHub_imu.settings_angular_velocity_threshold
.. blockimg:: pybricks_blockImuConfigure_PrimeHub_imu.settings_acceleration_threshold
.. automethod:: pybricks.hubs::PrimeHub.imu.settings
.. rubric:: Using the speaker
@@ -141,20 +150,6 @@ Prime Hub / Inventor Hub
.. automethod:: pybricks.hubs::PrimeHub.speaker.play_notes
.. rubric:: Using connectionless Bluetooth messaging
.. blockimg:: pybricks_blockBleBroadcast_PrimeHub
.. automethod:: pybricks.hubs::PrimeHub.ble.broadcast
.. blockimg:: pybricks_blockBleObserve_PrimeHub
.. automethod:: pybricks.hubs::PrimeHub.ble.observe
.. automethod:: pybricks.hubs::PrimeHub.ble.signal_strength
.. automethod:: pybricks.hubs::PrimeHub.ble.version
.. rubric:: Using the battery
.. blockimg:: pybricks_blockBatteryMeasure_PrimeHub_battery.voltage
@@ -175,19 +170,22 @@ Prime Hub / Inventor Hub
.. rubric:: System control
.. automethod:: pybricks.hubs::PrimeHub.system.name
.. automethod:: pybricks.hubs::PrimeHub.system.info
.. automethod:: pybricks.hubs::PrimeHub.system.storage
You can store up to 512 bytes of data on this hub.
You can store up to 512 bytes of data on this hub. The data is cleared
when you update the Pybricks firmware.
.. automethod:: pybricks.hubs::PrimeHub.system.reset_storage
.. blockimg:: pybricks_blockHubShutdown_PrimeHub
.. automethod:: pybricks.hubs::PrimeHub.system.shutdown
.. automethod:: pybricks.hubs::PrimeHub.system.reset_reason
.. note::
.. note:: The examples below use the ``PrimeHub`` class. The examples work fine
The examples below use the ``PrimeHub`` class. The examples work fine
on both hubs because they are the identical. If you prefer, you can
change this to ``InventorHub``.
@@ -317,23 +315,6 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_primehub.py
Bluetooth examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_broadcast_primehub.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_primehub.py
System examples
----------------------------------
+17 -38
View File
@@ -9,7 +9,6 @@ Technic Hub
.. blockimg:: pybricks_variables_set_technic_hub_option0
.. blockimg:: pybricks_variables_set_technic_hub_option4
:stack:
.. autoclass:: pybricks.hubs.TechnicHub
:no-members:
@@ -30,6 +29,13 @@ Technic Hub
.. rubric:: Using the IMU
.. versionchanged:: 3.6
The methods below now return calibrated data by default. Depending on
the method used, this combines data from the accelerometer, gyroscope,
with your calibration values. Use ``calibrated=False`` where applicable
to get the raw data you got before.
.. blockimg:: pybricks_blockImuStatus_TechnicHub_ready
.. automethod:: pybricks.hubs::TechnicHub.imu.ready
@@ -45,7 +51,6 @@ Technic Hub
.. blockimg:: pybricks_blockTilt_TechnicHub_imu.tilt.pitch
.. blockimg:: pybricks_blockTilt_TechnicHub_imu.tilt.roll
:stack:
.. automethod:: pybricks.hubs::TechnicHub.imu.tilt
@@ -71,22 +76,14 @@ Technic Hub
.. automethod:: pybricks.hubs::TechnicHub.imu.orientation
.. blockimg:: pybricks_blockImuConfigure_TechnicHub_imu.settings_heading_correction
.. blockimg:: pybricks_blockImuConfigure_TechnicHub_imu.settings_angular_velocity_threshold
.. blockimg:: pybricks_blockImuConfigure_TechnicHub_imu.settings_acceleration_threshold
.. automethod:: pybricks.hubs::TechnicHub.imu.settings
.. rubric:: Using connectionless Bluetooth messaging
.. blockimg:: pybricks_blockBleBroadcast_TechnicHub
.. automethod:: pybricks.hubs::TechnicHub.ble.broadcast
.. blockimg:: pybricks_blockBleObserve_TechnicHub
.. automethod:: pybricks.hubs::TechnicHub.ble.observe
.. automethod:: pybricks.hubs::TechnicHub.ble.signal_strength
.. automethod:: pybricks.hubs::TechnicHub.ble.version
.. rubric:: Using the battery
.. blockimg:: pybricks_blockBatteryMeasure_TechnicHub_battery.voltage
@@ -103,27 +100,26 @@ Technic Hub
.. automethod:: pybricks.hubs::TechnicHub.buttons.pressed
.. automethod:: pybricks.hubs::TechnicHub.system.info
.. blockimg:: pybricks_blockHubStopButton_TechnicHub
.. blockimg:: pybricks_blockHubStopButton_TechnicHub_none
:stack:
.. automethod:: pybricks.hubs::TechnicHub.system.set_stop_button
.. automethod:: pybricks.hubs::TechnicHub.system.name
.. automethod:: pybricks.hubs::TechnicHub.system.storage
You can store up to 128 bytes of data on this hub. The data is cleared
when you update the Pybricks firmware or if you restore the original
firmware.
.. automethod:: pybricks.hubs::TechnicHub.system.reset_storage
.. blockimg:: pybricks_blockHubShutdown_TechnicHub
.. automethod:: pybricks.hubs::TechnicHub.system.shutdown
.. automethod:: pybricks.hubs::TechnicHub.system.reset_reason
Status light examples
---------------------
@@ -185,23 +181,6 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_technichub.py
Bluetooth examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_broadcast_technichub.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_technichub.py
Button and system examples
----------------------------------
+1
View File
@@ -60,6 +60,7 @@ above to reveal this menu.
parameters/index
tools/index
robotics
messaging/index
signaltypes
.. toctree::
+3 -5
View File
@@ -1,10 +1,8 @@
EV3 Analog Sensor
.. pybricks-requirements:: pybricks-iodevices ev3
Analog Sensor
^^^^^^^^^^^^^^^^^
.. note::
This class is only available on EV3.
.. figure:: ../../main/cad/output/iodevice-rj12brown.png
:width: 25 %
+11 -4
View File
@@ -1,10 +1,14 @@
EV3 DC Motor
DC Motor
^^^^^^^^^^^^^^^^^^
.. note::
This class is specifically for EV3 and NXT. This lets you drive motors that
are not automatically detected as motors. This includes RCX motors and Power
Function motors that are connected via the official converter cables. Note:
Applying motor power to custom electronics may damage the hub or the device.
This class is specifically for on EV3. For Powered Up DC Motors, just use
the :class:`DCMotor <pybricks.pupdevices.DCMotor>` class.
For Powered Up DC Motors, just use
the :class:`DCMotor <pybricks.pupdevices.DCMotor>` class instead, which will
automatically detect the motor and use the correct and safe settings.
.. figure:: ../../main/cad/output/iodevice-dcmotor.png
:width: 40 %
@@ -16,5 +20,8 @@ EV3 DC Motor
.. automethod:: pybricks.iodevices.DCMotor.dc
:noindex:
.. automethod:: pybricks.iodevices.DCMotor.brake
:noindex:
.. automethod:: pybricks.iodevices.DCMotor.stop
:noindex:
-60
View File
@@ -1,60 +0,0 @@
Ev3dev sensors
^^^^^^^^^^^^^^^^^^
.. note::
This class is only available on EV3.
.. figure:: ../../main/cad/output/iodevice-rj12pcbbox.png
:width: 30 %
EV3 MicroPython is built on top of ev3dev, which means that a sensor
may be supported even if it is not listed in this documentation. If so, you can
use it with the ``Ev3devSensor`` class. This is easier and faster than using
the custom device classes given above.
To check whether you can use the ``Ev3devSensor`` class:
* Plug the sensor into your EV3 Brick.
* Go to the main menu of the EV3 Brick.
* Select `Device Browser` and then `Sensors`.
* If your sensor shows up, you can use it.
Now select your sensor from the menu and choose `set mode`. This shows all
available modes for this sensor. You can use these mode names as the ``mode``
setting below.
To learn more about compatible devices and what each mode does,
visit the `ev3dev sensors`_ page.
.. autoclass:: pybricks.iodevices.Ev3devSensor
:no-members:
.. autoattribute:: pybricks.iodevices.Ev3devSensor.sensor_index
:annotation:
.. autoattribute:: pybricks.iodevices.Ev3devSensor.port_index
:annotation:
.. automethod:: pybricks.iodevices.Ev3devSensor.read
**Example: Reading values with the Ev3devSensor class**
In this example we use the LEGO MINDSTORMS EV3 Color Sensor with the raw
RGB mode. This gives uncalibrated red, green, and blue reflection values.
.. literalinclude::
../../../examples/ev3/ev3devsensor/main.py
**Example: Extending the Ev3devSensor class**
This example shows how to extend the ``Ev3devSensor`` class by accessing
additional features found in the Linux system folder for this device.
.. literalinclude::
../../../examples/ev3/ev3devsensor/class_example.py
.. _ev3dev sensors: http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/sensors.html
.. _Mode name: http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/sensor_data.html
.. _lego-sensor: http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/sensors.html#the-lego-sensor-subsytem
.. _lego-port: http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/ports.html#the-lego-port-subsystem
+2 -8
View File
@@ -1,14 +1,8 @@
Generic I2C Device
^^^^^^^^^^^^^^^^^^
.. note::
This class is **only supported on the EV3** at this time. It could be added
to Powered Up hubs in a future release. If you'd like to see this happen, be
sure to ask us on our `support page`_.
.. _support page: https://github.com/pybricks/support/issues/
EV3 and NXT support connecting generic I2C devices to the hub.
See :doc:`pinout here <uartdevice>`.
.. figure:: ../../main/cad/output/iodevice-rj12cyan.png
:width: 25 %
+86 -12
View File
@@ -1,25 +1,39 @@
.. pybricks-requirements:: pybricks-iodevices
:mod:`iodevices <pybricks.iodevices>` -- Custom devices
============================================================
.. module:: pybricks.iodevices
This module has classes for generic and custom input/output devices.
Wireless devices
----------------
.. toctree::
:maxdepth: 1
:hidden:
pupdevice
lwp3device
xboxcontroller
This module has classes for generic and custom input/output devices.
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: PUPDevice
.. pybricks-classlink:: XboxController
.. figure:: ../../main/cad/output/iodevice-pupdevice.png
:width: 50 %
:target: pupdevice.html
.. figure:: ../../main/diagrams_source/xboxcontroller.png
:width: 40 %
:target: xboxcontroller.html
LEGO protocol devices
---------------------
.. toctree::
:maxdepth: 1
:hidden:
lwp3device
lumpdevice
pupdevice
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: LWP3Device
@@ -27,8 +41,68 @@ This module has classes for generic and custom input/output devices.
:width: 80 %
:target: lwp3device.html
.. pybricks-classlink:: XboxController
.. pybricks-requirements:: ev3 pybricks-iodevices
.. figure:: ../../main/diagrams_source/xboxcontroller.png
.. pybricks-classlink:: LUMPDevice
.. figure:: ../../main/cad/output/iodevice-rj12green.png
:width: 20 %
:target: lumpdevice.html
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: PUPDevice
.. figure:: ../../main/cad/output/iodevice-pupdevice.png
:width: 50 %
:target: pupdevice.html
Generic protocols
-----------------
.. toctree::
:maxdepth: 1
:hidden:
uartdevice
i2cdevice
analogsensor
dcmotor
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: UARTDevice
.. |uart-wired| image:: ../../main/cad/output/iodevice-rj12grey.png
:width: 20 %
:target: uartdevice.html
.. |uart-wireless| image:: ../../main/cad/output/iodevice-pupdevice.png
:width: 50 %
:target: uartdevice.html
|uart-wired| |uart-wireless|
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-classlink:: I2CDevice
.. figure:: ../../main/cad/output/iodevice-rj12cyan.png
:width: 20 %
:target: i2cdevice.html
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-classlink:: AnalogSensor
.. figure:: ../../main/cad/output/iodevice-rj12brown.png
:width: 20 %
:target: analogsensor.html
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-classlink:: DCMotor
.. figure:: ../../main/cad/output/iodevice-dcmotor.png
:width: 40 %
:target: xboxcontroller.html
:target: dcmotor.html
+3 -4
View File
@@ -1,11 +1,10 @@
.. pybricks-requirements:: pybricks-iodevices ev3
EV3 UART Device
^^^^^^^^^^^^^^^^^
.. note::
This class is only available on EV3.
.. figure:: ../../main/cad/output/iodevice-rj12green.png
:width: 25 %
.. autoclass:: pybricks.iodevices.LUMPDevice
:no-members:
+2 -5
View File
@@ -1,11 +1,8 @@
.. pybricks-requirements:: pybricks-iodevices
LEGO Wireless Protocol v3 device
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. warning::
This is an experimental class. It has not been well tested and may be
changed in future.
.. figure:: ../../main/cad/output/hub-lwp3.png
:width: 80 %
Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

+2
View File
@@ -15,6 +15,8 @@ Powered Up Device
.. automethod:: pybricks.iodevices.PUPDevice.write
.. automethod:: pybricks.iodevices.PUPDevice.reset
Examples
-------------------
+38 -7
View File
@@ -1,16 +1,47 @@
.. pybricks-requirements:: pybricks-iodevices
Generic UART Device
^^^^^^^^^^^^^^^^^^^
.. note::
Powered Up and EV3 support connecting generic UART devices to the hub. The pinout
is shown below. Note the orientation of the connector. For EV3, the internal
wire colors match those on the diagram below.
This class is **only supported on the EV3** at this time. It could be added
to Powered Up hubs in a future release. If you'd like to see this happen,
be sure to ask us on our `support page`_.
.. image:: pinout_numbered.jpg
:width: 50 %
.. _support page: https://github.com/pybricks/support/issues/
.. list-table::
:header-rows: 1
* - Pin
- Powered Up (UART)
- EV3 (UART sensor)
- EV3 (I2C sensor)
* - 1 (white)
- Motor Terminal 1
- Optional battery power
- Optional battery power
* - 2 (black)
- Motor Terminal 2
- N/A
- N/A
* - 3 (red)
- Ground
- Ground
- Ground
* - 4 (green)
- VCC (3.3 V)
- VCC (5 V)
- VCC (5 V)
* - 5 (yellow)
- Hub TX (Sensor RX) (3.3 V)
- Hub TX (Sensor RX) (3.3 V)
- SCL (master) (3.3 V)
* - 6 (blue)
- Hub RX (Sensor TX) (3.3 V)
- Hub RX (Sensor TX) (3.3 V)
- SDA (master) (3.3 V)
.. figure:: ../../main/cad/output/iodevice-rj12grey.png
:width: 25 %
.. autoclass:: pybricks.iodevices.UARTDevice
+9 -8
View File
@@ -11,6 +11,12 @@ Xbox Controller
.. autoclass:: pybricks.iodevices.XboxController
:no-members:
.. automethod:: pybricks.iodevices::XboxController.connect
.. automethod:: pybricks.iodevices::XboxController.disconnect
.. automethod:: pybricks.iodevices::XboxController.name
.. blockimg:: pybricks_blockButtonIsPressed_XboxController
.. automethod:: pybricks.iodevices::XboxController.buttons.pressed
@@ -30,21 +36,18 @@ Xbox Controller
.. blockimg:: pybricks_blockJoystickValue_lj_x
.. blockimg:: pybricks_blockJoystickValue_lj_y
:stack:
.. automethod:: pybricks.iodevices::XboxController.joystick_left
.. blockimg:: pybricks_blockJoystickValue_rj_x
.. blockimg:: pybricks_blockJoystickValue_rj_y
:stack:
.. automethod:: pybricks.iodevices::XboxController.joystick_right
.. blockimg:: pybricks_blockJoystickValue_lt
.. blockimg:: pybricks_blockJoystickValue_rt
:stack:
.. automethod:: pybricks.iodevices::XboxController.triggers
@@ -59,17 +62,15 @@ Xbox Controller
.. blockimg:: pybricks_blockGamepadRumble_default
.. blockimg:: pybricks_blockGamepadRumble_default_with_list
:stack:
.. blockimg:: pybricks_blockGamepadRumble_with_options
:stack:
.. automethod:: pybricks.iodevices::XboxController.rumble
.. _xbox-controller-pairing:
Xbox Controller Pairing Instructions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
====================================
The first time you use a controller with a hub, you will need to pair
them: Turn the controller on and then press and hold the pairing
button on the back of the controller for a few seconds. When you release
@@ -79,7 +80,7 @@ When pairing and the connection is succesful, the Xbox button will stop
flashing and stay on for as long as the program is running.
Repeat Connections
==================
------------------
If you keep using the same controller with the same hub, you can simply
turn the controller on the next time and the hub will connect to it
@@ -91,7 +92,7 @@ connect to another hub, you will need to pair them again as described
above.
Compatible Controllers
============================
----------------------
All Xbox controllers released since 2016 are compatible. This includes the
controller from the One S (``1708`` from 2016), the Elite Series 2 (``1797``
+44
View File
@@ -0,0 +1,44 @@
:mod:`messaging <pybricks.messaging>` -- Send and receive messages
==================================================================
.. automodule:: pybricks.messaging
:no-members:
.. pybricks-requirements:: pup
.. autoclass:: pybricks.messaging.BLERadio
:no-members:
.. automethod:: pybricks.messaging.BLERadio.broadcast
.. automethod:: pybricks.messaging.BLERadio.observe
.. automethod:: pybricks.messaging.BLERadio.signal_strength
.. automethod:: pybricks.messaging.BLERadio.version
.. autoclass:: pybricks.messaging.AppData
:no-members:
.. automethod:: pybricks.messaging.AppData.get_bytes
.. automethod:: pybricks.messaging.AppData.write_bytes
.. automethod:: pybricks.messaging.AppData.configure
.. automethod:: pybricks.messaging.AppData.close
BLERadio examples
------------------
Broadcasting data to other hubs
*******************************
.. literalinclude::
../../../examples/pup/ble_radio/ble_broadcast.py
Observing data from other hubs
******************************
.. literalinclude::
../../../examples/pup/ble_radio/ble_observe.py
+2 -18
View File
@@ -79,52 +79,36 @@ Sequences
.. pybricks-requirements::
.. blockimg:: pybricks_blockListCreate_list_empty
:stack:
.. blockimg:: pybricks_blockListCreate_list_3
:stack:
.. blockimg:: pybricks_blockListUnpack
:stack:
.. blockimg:: pybricks_blockListGet_list_get_first
:stack:
.. blockimg:: pybricks_blockListGet_list_get_index
:stack:
.. blockimg:: pybricks_blockListGet_list_get_last
:stack:
.. blockimg:: pybricks_blockListGet_list_get_random
:stack:
.. blockimg:: pybricks_blockListSet_list_insert_first
:stack:
.. blockimg:: pybricks_blockListSet_list_insert_index
:stack:
.. blockimg:: pybricks_blockListSet_list_insert_last
:stack:
.. blockimg:: pybricks_blockListSet_list_remove_first
:stack:
.. blockimg:: pybricks_blockListSet_list_remove_index
:stack:
.. blockimg:: pybricks_blockListSet_list_remove_last
:stack:
.. blockimg:: pybricks_blockListSet_list_set_first
:stack:
.. blockimg:: pybricks_blockListSet_list_set_index
:stack:
.. blockimg:: pybricks_blockListSet_list_set_last
:stack:
.. autoclass:: ubuiltins.list
@@ -262,11 +246,11 @@ See also :mod:`umath` for floating point math operations.
Runtime functions
-------------------------
.. pybricks-requirements::
.. pybricks-requirements:: stm32-extra
.. autofunction:: ubuiltins.eval
.. pybricks-requirements::
.. pybricks-requirements:: stm32-extra
.. autofunction:: ubuiltins.exec
-1
View File
@@ -42,7 +42,6 @@ Color Sensor
.. blockimg:: pybricks_blockLightOn_colorsensor_on
.. blockimg:: pybricks_blockLightOn_colorsensor_on_list
:stack:
.. automethod:: pybricks.pupdevices::ColorSensor.lights.on
+23
View File
@@ -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
+15
View File
@@ -22,6 +22,9 @@
colorlightmatrix
light
remote
technicmovehub
mariohub
duplotrain
.. pybricks-classlink:: DCMotor
@@ -94,3 +97,15 @@
.. figure:: ../../main/cad/output/pupdevice-remote.png
:width: 50 %
: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
+17
View File
@@ -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
-2
View File
@@ -105,10 +105,8 @@ Motors with rotation sensors
.. blockimg:: pybricks_blockMotorConfigure_motor_max_speed
.. blockimg:: pybricks_blockMotorConfigure_motor_acceleration
:stack:
.. blockimg:: pybricks_blockMotorConfigure_motor_max_torque
:stack:
.. automethod:: pybricks.pupdevices.Motor.control.limits
+2 -1
View File
@@ -9,11 +9,12 @@ Remote Control
.. blockimg:: pybricks_variables_set_remote_connect_any
.. blockimg:: pybricks_variables_set_remote_connect_name
:stack:
.. autoclass:: pybricks.pupdevices.Remote
:no-members:
.. automethod:: pybricks.pupdevices::Remote.connect
.. automethod:: pybricks.pupdevices::Remote.name
.. blockimg:: pybricks_blockLightOnColor_remote_on
+13
View File
@@ -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
-1
View File
@@ -14,7 +14,6 @@ Tilt Sensor
.. blockimg:: pybricks_blockTilt_TiltSensor_imu.tilt.pitch
.. blockimg:: pybricks_blockTilt_TiltSensor_imu.tilt.roll
:stack:
.. automethod:: tilt
-1
View File
@@ -25,7 +25,6 @@ Ultrasonic Sensor
.. blockimg:: pybricks_blockLightOn_ultrasonicsensor_on
.. blockimg:: pybricks_blockLightOn_ultrasonicsensor_on_list
:stack:
.. automethod:: pybricks.pupdevices::UltrasonicSensor.lights.on
+17 -3
View File
@@ -27,9 +27,15 @@
.. automethod:: pybricks.robotics.DriveBase.turn
.. blockimg:: pybricks_blockDriveBaseDrive_drivebase_drive_curve
.. blockimg:: pybricks_blockDriveBaseDrive2_drivebase_drive_arc_angle
.. automethod:: pybricks.robotics.DriveBase.curve
.. blockimg:: pybricks_blockDriveBaseDrive2_drivebase_drive_arc_distance
.. automethod:: pybricks.robotics.DriveBase.arc
.. pybricks-requirements:: stm32-float
.. automethod:: pybricks.robotics.DriveBase.move_by
.. blockimg:: pybricks_blockDriveBaseConfigure_drivebase_straight_speed
@@ -65,6 +71,8 @@
.. blockimg:: pybricks_blockDriveBaseStop_hold
.. automethod:: pybricks.robotics.DriveBase.hold
.. rubric:: Measuring
.. blockimg:: pybricks_blockDriveBaseMeasure_drivebase_get_distance
@@ -81,6 +89,12 @@
.. automethod:: pybricks.robotics.DriveBase.state
.. versionchanged:: 3.6
Now stops the drive base. You can now use nonzero values.
.. blockimg:: pybricks_blockDriveBaseResetWithValues
.. automethod:: pybricks.robotics.DriveBase.reset
.. automethod:: pybricks.robotics.DriveBase.stalled
@@ -114,7 +128,7 @@
``then=Stop.COAST`` in your last
:meth:`straight <pybricks.robotics.DriveBase.straight>`,
:meth:`turn <pybricks.robotics.DriveBase.turn>`, or
:meth:`curve <pybricks.robotics.DriveBase.curve>` command.
:meth:`curve <pybricks.robotics.DriveBase.arc>` command.
.. _measuring:
-3
View File
@@ -40,13 +40,10 @@ Input tools
.. blockimg:: pybricks_blockReadInput_read_input_first_byte
.. blockimg:: pybricks_blockReadInput_read_input_first_char
:stack:
.. blockimg:: pybricks_blockReadInput_read_input_last_byte
:stack:
.. blockimg:: pybricks_blockReadInput_read_input_last_char
:stack:
.. autofunction:: pybricks.tools.read_input_byte
+1 -1
View File
@@ -10,7 +10,7 @@ ev3 = EV3Brick()
device = I2CDevice(Port.S2, 0xD2 >> 1)
# Recommended for reading
(result,) = device.read(reg=0x0F, length=1)
result = device.read(reg=0x0F, length=1)
# Read 1 byte from no particular register:
device.read(reg=None, length=1)
@@ -1,11 +1,10 @@
# ThisHub = MoveHub CityHub TechnicHub PrimeHub EssentialHub
from pybricks.hubs import ThisHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait
from pybricks.messaging import BLERadio
# Initialize the hub.
hub = ThisHub(broadcast_channel=1)
radio = BLERadio(broadcast_channel=1)
# Initialize the motors.
left_motor = Motor(Port.A)
@@ -18,7 +17,7 @@ while True:
# Set the broadcast data and start broadcasting if not already doing so.
data = (left_angle, right_angle)
hub.ble.broadcast(data)
radio.broadcast(data)
# Broadcasts are only sent every 100 milliseconds, so there is no reason
# to call the broadcast() method more often than that.
@@ -1,11 +1,10 @@
# ThisHub = MoveHub CityHub TechnicHub PrimeHub EssentialHub
from pybricks.hubs import ThisHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Color, Port
from pybricks.parameters import Port
from pybricks.tools import wait
from pybricks.messaging import BLERadio
# Initialize the hub.
hub = ThisHub(observe_channels=[1])
radio = BLERadio(observe_channels=[1])
# Initialize the motors.
left_motor = Motor(Port.A)
@@ -14,17 +13,12 @@ right_motor = Motor(Port.B)
while True:
# Receive broadcast from the other hub.
data = hub.ble.observe(1)
data = radio.observe(1)
if data is None:
# No data has been received in the last 1 second.
hub.light.on(Color.RED)
else:
if data is not None:
# Data was received and is less that one second old.
hub.light.on(Color.GREEN)
# *data* contains the same values in the same order
# that were passed to hub.ble.broadcast() on the
# It contains the same values in the same order
# that were passed to radio.broadcast() on the
# other hub.
left_angle, right_angle = data
+1 -1
View File
@@ -12,7 +12,7 @@ wait(1500)
example_motor.stop()
wait(1500)
# Run at 70% duty cycle ("power") and then stop by coasting.
# Run at 50% duty cycle ("power") and then stop by coasting.
print("Demo of dc")
example_motor.dc(50)
wait(1500)
+10
View File
@@ -4,6 +4,16 @@
## Unreleased
## 1.17.0 - 2025-02-26
### Changed
- Updated `pybricks` package to v3.5.0b5.
## 1.16.0 - 2024-04-05
### Changed
- Updated `pybricks` package to v3.5.0b2.
## 1.15.0 - 2024-03-21
### Changed
+62 -52
View File
@@ -1,10 +1,9 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "black"
version = "22.12.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -37,14 +36,13 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "click"
version = "8.1.7"
version = "8.1.8"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
{file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
{file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
]
[package.dependencies]
@@ -54,7 +52,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -66,7 +63,6 @@ files = [
name = "docstring-parser"
version = "0.14.1"
description = "Parse Python docstrings in reST, Google and Numpydoc format"
category = "main"
optional = false
python-versions = ">=3.6,<4.0"
files = [
@@ -76,14 +72,13 @@ files = [
[[package]]
name = "exceptiongroup"
version = "1.2.0"
version = "1.2.2"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
{file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[package.extras]
@@ -93,7 +88,6 @@ test = ["pytest (>=6)"]
name = "flake8"
version = "4.0.1"
description = "the modular source code checker: pep8 pyflakes and co"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -110,7 +104,6 @@ pyflakes = ">=2.4.0,<2.5.0"
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -122,7 +115,6 @@ files = [
name = "jedi"
version = "0.18.1"
description = "An autocompletion tool for Python that can be used for text editors."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -141,7 +133,6 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"]
name = "mccabe"
version = "0.6.1"
description = "McCabe checker, plugin for flake8"
category = "dev"
optional = false
python-versions = "*"
files = [
@@ -153,7 +144,6 @@ files = [
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -163,37 +153,34 @@ files = [
[[package]]
name = "packaging"
version = "24.0"
version = "24.2"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
{file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
]
[[package]]
name = "parso"
version = "0.8.3"
version = "0.8.4"
description = "A Python Parser"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
{file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"},
{file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"},
]
[package.extras]
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["docopt", "pytest (<6.0.0)"]
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
testing = ["docopt", "pytest"]
[[package]]
name = "pathspec"
version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -203,30 +190,29 @@ files = [
[[package]]
name = "platformdirs"
version = "4.2.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
version = "4.3.6"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.8"
files = [
{file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
{file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
{file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
{file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
]
[package.extras]
docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"]
type = ["mypy (>=1.11.2)"]
[[package]]
name = "pluggy"
version = "1.4.0"
version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
{file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[package.extras]
@@ -235,9 +221,8 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pybricks"
version = "v3.5.0b1"
version = "3.6.0b5"
description = "Documentation and user-API stubs for Pybricks MicroPython"
category = "main"
optional = false
python-versions = "^3.8"
files = []
@@ -251,7 +236,6 @@ url = ".."
name = "pycodestyle"
version = "2.8.0"
description = "Python style guide checker"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -263,7 +247,6 @@ files = [
name = "pyflakes"
version = "2.4.0"
description = "passive checker of Python programs"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -275,7 +258,6 @@ files = [
name = "pytest"
version = "7.4.4"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -296,21 +278,49 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
[[package]]
name = "tomli"
version = "2.0.1"
version = "2.2.1"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
{file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
{file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
{file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
{file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
{file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
{file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
{file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
{file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
{file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
{file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
{file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
{file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
]
[[package]]
name = "typing-extensions"
version = "4.2.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -321,4 +331,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = ">= 3.10, < 3.12"
content-hash = "ed8e7ae0c6ccd2be4b216c32cb496645b37aa63539c2a4738ef6fd8122ec6e2d"
content-hash = "0a796ac6867c41e8cf0ce289beca1cebb4066b622c2c538c11589413dcb579af"
+3 -2
View File
@@ -1,13 +1,14 @@
[tool.poetry]
name = "pybricks_jedi"
version = "1.15.0"
# Version is set automatically at build time from the root pyproject.toml. Do not edit.
version = "0.0.0"
description = "Code completion for Pybricks."
authors = ["The Pybricks Authors <team@pybricks.com>"]
license = "MIT"
[tool.poetry.dependencies]
python = ">= 3.10, < 3.12"
pybricks = "3.5.0b1"
pybricks = "3.6.0b5"
jedi = "0.18.1"
typing-extensions = "4.2.0"
docstring-parser = "0.14.1"
+2
View File
@@ -15,6 +15,7 @@ PYBRICKS_CODE_PACKAGES = {
"pybricks",
"pybricks.hubs",
"pybricks.iodevices",
"pybricks.messaging",
"pybricks.parameters",
"pybricks.pupdevices",
"pybricks.robotics",
@@ -490,6 +491,7 @@ def initialize():
"pybricks.ev3dev.speaker",
"pybricks.hubs",
"pybricks.iodevices",
"pybricks.messaging",
"pybricks.parameters",
"pybricks.pupdevices",
"pybricks.robotics",
+2 -4
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the CityHub class.
"""
import json
from pybricks_jedi import CompletionItem, complete
@@ -33,7 +32,6 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"buttons",
"light",
"system",
@@ -76,8 +74,8 @@ def test_hub_dot_system_dot():
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"name",
"reset_reason",
"info",
"reset_storage",
"set_stop_button",
"shutdown",
"storage",
+2 -4
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the EssentialHub class.
"""
import json
from pybricks_jedi import CompletionItem, complete
@@ -33,7 +32,6 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"buttons",
"charger",
"imu",
@@ -108,8 +106,8 @@ def test_hub_dot_system_dot():
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"name",
"reset_reason",
"info",
"reset_storage",
"set_stop_button",
"shutdown",
"storage",
+5 -1
View File
@@ -61,6 +61,7 @@ def test_from_pybricks_import():
assert [c["insertText"] for c in completions] == [
"hubs",
"iodevices",
"messaging",
"parameters",
"pupdevices",
"robotics",
@@ -75,6 +76,7 @@ def test_from_pybricks_dot():
assert [c["insertText"] for c in completions] == [
"hubs",
"iodevices",
"messaging",
"parameters",
"pupdevices",
"robotics",
@@ -102,7 +104,6 @@ def test_from_pybricks_iodevices_import():
assert [c["insertText"] for c in completions] == [
"AnalogSensor",
"DCMotor",
"Ev3devSensor",
"I2CDevice",
"LUMPDevice",
"LWP3Device",
@@ -135,12 +136,15 @@ def test_from_pybricks_pupdevices_import():
"ColorLightMatrix",
"ColorSensor",
"DCMotor",
"DuploTrain",
"ForceSensor",
"InfraredSensor",
"Light",
"MarioHub",
"Motor",
"PFMotor",
"Remote",
"TechnicMoveHub",
"TiltSensor",
"UltrasonicSensor",
]
-1
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the InventorHub class.
"""
import json
from pybricks_jedi import complete, CompletionItem
+61
View File
@@ -0,0 +1,61 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 The Pybricks Authors
"""
Tests for correct code completion of the messaging module.
"""
import json
import pytest
from pybricks_jedi import CompletionItem, complete
def test_from_pybricks_messaging_import():
code = "from pybricks.messaging import "
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
assert [c["insertText"] for c in completions] == [
"AppData",
"BLERadio",
"BluetoothMailboxClient",
"BluetoothMailboxServer",
"Connection",
"LogicMailbox",
"Mailbox",
"NumericMailbox",
"TextMailbox",
]
def test_ble_radio_dot():
code = "\n".join(
[
"from pybricks.messaging import BLERadio",
"ble = BLERadio()",
"ble.",
]
)
completions: list[CompletionItem] = json.loads(complete(code, 3, 5))
assert [c["insertText"] for c in completions] == [
"broadcast",
"observe",
"signal_strength",
"version",
]
def test_app_data_dot():
code = "\n".join(
[
"from pybricks.messaging import AppData",
"app = AppData([(0, 4)])",
"app.",
]
)
completions: list[CompletionItem] = json.loads(complete(code, 3, 5))
assert [c["insertText"] for c in completions] == [
"close",
"configure",
"get_bytes",
"write_bytes",
]
+2 -4
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the MoveHub class.
"""
import json
from pybricks_jedi import CompletionItem, complete
@@ -33,7 +32,6 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"buttons",
"imu",
"light",
@@ -88,8 +86,8 @@ def test_hub_dot_system_dot():
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"name",
"reset_reason",
"info",
"reset_storage",
"set_stop_button",
"shutdown",
"storage",
+2 -4
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the PrimeHub class.
"""
import json
from pybricks_jedi import CompletionItem, complete
@@ -33,7 +32,6 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"buttons",
"charger",
"display",
@@ -137,8 +135,8 @@ def test_hub_dot_system_dot():
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"name",
"reset_reason",
"info",
"reset_storage",
"set_stop_button",
"shutdown",
"storage",
+2 -4
View File
@@ -5,7 +5,6 @@
Tests for correct code completion of the TechnicHub class.
"""
import json
from pybricks_jedi import CompletionItem, complete
@@ -33,7 +32,6 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"buttons",
"imu",
"light",
@@ -96,8 +94,8 @@ def test_hub_dot_system_dot():
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"name",
"reset_reason",
"info",
"reset_storage",
"set_stop_button",
"shutdown",
"storage",
+83 -42
View File
@@ -5,7 +5,6 @@
Tests for correct signatures of the pupdevices.Motor class.
"""
from itertools import zip_longest
import json
@@ -86,12 +85,17 @@ CONSTRUCTOR_PARAMS = [
pytest.param(
"pybricks.hubs",
"MoveHub",
[["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
[
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
]
],
),
pytest.param(
"pybricks.hubs",
"CityHub",
[["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
[[]],
),
pytest.param(
"pybricks.hubs",
@@ -100,8 +104,6 @@ CONSTRUCTOR_PARAMS = [
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
@@ -112,8 +114,6 @@ CONSTRUCTOR_PARAMS = [
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
@@ -124,8 +124,6 @@ CONSTRUCTOR_PARAMS = [
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
@@ -170,7 +168,7 @@ CONSTRUCTOR_PARAMS = [
pytest.param(
"pybricks.pupdevices",
"Remote",
[["name: Optional[str]=None", "timeout: int=10000"]],
[["name: Optional[str]=None", "timeout: int=10000", "connect: bool=True"]],
),
# TODO: iodevices go here
pytest.param(
@@ -264,7 +262,6 @@ METHOD_PARAMS = [
"system.set_stop_button",
[(["button: Optional[Union[Button, Iterable[Button]]]"], "None")],
),
pytest.param("pybricks.hubs", "MoveHub", "system.name", [([], "str")]),
pytest.param("pybricks.hubs", "MoveHub", "system.shutdown", [([], "None")]),
pytest.param(
"pybricks.hubs",
@@ -275,7 +272,6 @@ METHOD_PARAMS = [
(["offset: int", "*", "write: bytes"], "None"),
],
),
pytest.param("pybricks.hubs", "MoveHub", "system.reset_reason", [([], "int")]),
pytest.param("pybricks.hubs", "CityHub", "light.on", [(["color: Color"], "None")]),
pytest.param("pybricks.hubs", "CityHub", "light.off", [([], "None")]),
pytest.param(
@@ -299,7 +295,6 @@ METHOD_PARAMS = [
"system.set_stop_button",
[(["button: Optional[Union[Button, Iterable[Button]]]"], "None")],
),
pytest.param("pybricks.hubs", "CityHub", "system.name", [([], "str")]),
pytest.param("pybricks.hubs", "CityHub", "system.shutdown", [([], "None")]),
pytest.param(
"pybricks.hubs",
@@ -310,7 +305,6 @@ METHOD_PARAMS = [
(["offset: int", "*", "write: bytes"], "None"),
],
),
pytest.param("pybricks.hubs", "CityHub", "system.reset_reason", [([], "int")]),
pytest.param(
"pybricks.hubs", "TechnicHub", "light.on", [(["color: Color"], "None")]
),
@@ -327,19 +321,35 @@ METHOD_PARAMS = [
"light.animate",
[(["colors: Collection[Color]", "interval: Number"], "None")],
),
pytest.param("pybricks.hubs", "TechnicHub", "imu.up", [([], "Side")]),
pytest.param("pybricks.hubs", "TechnicHub", "imu.tilt", [([], "Tuple[int, int]")]),
pytest.param(
"pybricks.hubs",
"TechnicHub",
"imu.up",
[(["calibrated: bool=True"], "Side")],
),
pytest.param(
"pybricks.hubs",
"TechnicHub",
"imu.tilt",
[(["calibrated: bool=True"], "Tuple[int, int]")],
),
pytest.param(
"pybricks.hubs",
"TechnicHub",
"imu.acceleration",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param(
"pybricks.hubs",
"TechnicHub",
"imu.angular_velocity",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param("pybricks.hubs", "TechnicHub", "imu.heading", [([], "float")]),
pytest.param("pybricks.hubs", "TechnicHub", "imu.orientation", [([], "Matrix")]),
@@ -353,7 +363,7 @@ METHOD_PARAMS = [
"pybricks.hubs",
"TechnicHub",
"imu.rotation",
[(["axis: Axis"], "float")],
[(["axis: Axis", "calibrated: bool=True"], "float")],
),
pytest.param("pybricks.hubs", "TechnicHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "TechnicHub", "battery.current", [([], "int")]),
@@ -366,7 +376,6 @@ METHOD_PARAMS = [
"system.set_stop_button",
[(["button: Optional[Union[Button, Iterable[Button]]]"], "None")],
),
pytest.param("pybricks.hubs", "TechnicHub", "system.name", [([], "str")]),
pytest.param("pybricks.hubs", "TechnicHub", "system.shutdown", [([], "None")]),
pytest.param(
"pybricks.hubs",
@@ -377,7 +386,6 @@ METHOD_PARAMS = [
(["offset: int", "*", "write: bytes"], "None"),
],
),
pytest.param("pybricks.hubs", "TechnicHub", "system.reset_reason", [([], "int")]),
pytest.param("pybricks.hubs", "PrimeHub", "light.on", [(["color: Color"], "None")]),
pytest.param("pybricks.hubs", "PrimeHub", "light.off", [([], "None")]),
pytest.param(
@@ -424,19 +432,32 @@ METHOD_PARAMS = [
[(["text: str", "on: Number=500", "off: Number=50"], "None")],
),
pytest.param("pybricks.hubs", "PrimeHub", "buttons.pressed", [([], "Set[Button]")]),
pytest.param("pybricks.hubs", "PrimeHub", "imu.up", [([], "Side")]),
pytest.param("pybricks.hubs", "PrimeHub", "imu.tilt", [([], "Tuple[int, int]")]),
pytest.param(
"pybricks.hubs", "PrimeHub", "imu.up", [(["calibrated: bool=True"], "Side")]
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
"imu.tilt",
[(["calibrated: bool=True"], "Tuple[int, int]")],
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
"imu.acceleration",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
"imu.angular_velocity",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param("pybricks.hubs", "PrimeHub", "imu.heading", [([], "float")]),
pytest.param("pybricks.hubs", "PrimeHub", "imu.orientation", [([], "Matrix")]),
@@ -450,7 +471,7 @@ METHOD_PARAMS = [
"pybricks.hubs",
"PrimeHub",
"imu.rotation",
[(["axis: Axis"], "float")],
[(["axis: Axis", "calibrated: bool=True"], "float")],
),
pytest.param(
"pybricks.hubs",
@@ -481,7 +502,6 @@ METHOD_PARAMS = [
"system.set_stop_button",
[(["button: Optional[Union[Button, Iterable[Button]]]"], "None")],
),
pytest.param("pybricks.hubs", "PrimeHub", "system.name", [([], "str")]),
pytest.param("pybricks.hubs", "PrimeHub", "system.shutdown", [([], "None")]),
pytest.param(
"pybricks.hubs",
@@ -492,7 +512,6 @@ METHOD_PARAMS = [
(["offset: int", "*", "write: bytes"], "None"),
],
),
pytest.param("pybricks.hubs", "PrimeHub", "system.reset_reason", [([], "int")]),
pytest.param(
"pybricks.hubs", "EssentialHub", "light.on", [(["color: Color"], "None")]
),
@@ -512,21 +531,32 @@ METHOD_PARAMS = [
pytest.param(
"pybricks.hubs", "EssentialHub", "buttons.pressed", [([], "Set[Button]")]
),
pytest.param("pybricks.hubs", "EssentialHub", "imu.up", [([], "Side")]),
pytest.param(
"pybricks.hubs", "EssentialHub", "imu.tilt", [([], "Tuple[int, int]")]
"pybricks.hubs", "EssentialHub", "imu.up", [(["calibrated: bool=True"], "Side")]
),
pytest.param(
"pybricks.hubs",
"EssentialHub",
"imu.tilt",
[(["calibrated: bool=True"], "Tuple[int, int]")],
),
pytest.param(
"pybricks.hubs",
"EssentialHub",
"imu.acceleration",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param(
"pybricks.hubs",
"EssentialHub",
"imu.angular_velocity",
[(["axis: Axis"], "float"), ([], "Matrix")],
[
(["axis: Axis=None", "calibrated: bool=True"], "float"),
(["calibrated: bool=True"], "Matrix"),
],
),
pytest.param("pybricks.hubs", "EssentialHub", "imu.heading", [([], "float")]),
pytest.param("pybricks.hubs", "EssentialHub", "imu.orientation", [([], "Matrix")]),
@@ -540,7 +570,7 @@ METHOD_PARAMS = [
"pybricks.hubs",
"EssentialHub",
"imu.rotation",
[(["axis: Axis"], "float")],
[(["axis: Axis", "calibrated: bool=True"], "float")],
),
pytest.param("pybricks.hubs", "EssentialHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "EssentialHub", "battery.current", [([], "int")]),
@@ -553,7 +583,6 @@ METHOD_PARAMS = [
"system.set_stop_button",
[(["button: Optional[Union[Button, Iterable[Button]]]"], "None")],
),
pytest.param("pybricks.hubs", "EssentialHub", "system.name", [([], "str")]),
pytest.param("pybricks.hubs", "EssentialHub", "system.shutdown", [([], "None")]),
pytest.param(
"pybricks.hubs",
@@ -564,7 +593,6 @@ METHOD_PARAMS = [
(["offset: int", "*", "write: bytes"], "None"),
],
),
pytest.param("pybricks.hubs", "EssentialHub", "system.reset_reason", [([], "int")]),
# TODO: iodevices module here
pytest.param("pybricks.pupdevices", "DCMotor", "dc", [(["duty: Number"], "None")]),
pytest.param("pybricks.pupdevices", "DCMotor", "stop", [([], "None")]),
@@ -905,7 +933,7 @@ METHOD_PARAMS = [
"pybricks.pupdevices",
"Remote",
"name",
[(["name: str"], "None"), ([], "str")],
[(["name: str"], "MaybeAwaitable"), ([], "str")],
),
pytest.param(
"pybricks.pupdevices",
@@ -943,7 +971,12 @@ METHOD_PARAMS = [
"turn",
[
(
["angle: Number", "then: Stop=Stop.HOLD", "wait: bool=True"],
[
"angle: Number",
"then: Stop=Stop.HOLD",
"wait: bool=True",
"absolute: bool=False",
],
"MaybeAwaitable",
)
],
@@ -972,13 +1005,16 @@ METHOD_PARAMS = [
(
[
"straight_speed: Optional[Number]=None",
"straight_acceleration: Optional[Number]=None",
"straight_acceleration: Optional[Union[Number, Tuple[Number, Number]]]=None",
"turn_rate: Optional[Number]=None",
"turn_acceleration: Optional[Number]=None",
"turn_acceleration: Optional[Union[Number, Tuple[Number, Number]]]=None",
],
"None",
),
([], "Tuple[int, int, int, int]"),
(
[],
"Tuple[int, Union[int, Tuple[int, int]], int, Union[int, Tuple[int, int]]]",
),
],
),
pytest.param(
@@ -990,11 +1026,16 @@ METHOD_PARAMS = [
pytest.param("pybricks.robotics", "DriveBase", "stop", [([], "None")]),
pytest.param("pybricks.robotics", "DriveBase", "brake", [([], "None")]),
pytest.param("pybricks.robotics", "DriveBase", "distance", [([], "int")]),
pytest.param("pybricks.robotics", "DriveBase", "angle", [([], "int")]),
pytest.param("pybricks.robotics", "DriveBase", "angle", [([], "float")]),
pytest.param(
"pybricks.robotics", "DriveBase", "state", [([], "Tuple[int, int, int, int]")]
),
pytest.param("pybricks.robotics", "DriveBase", "reset", [([], "None")]),
pytest.param(
"pybricks.robotics",
"DriveBase",
"reset",
[(["distance: Number=0", "angle: Number=0"], "None")],
),
pytest.param("pybricks.robotics", "DriveBase", "done", [([], "bool")]),
pytest.param("pybricks.robotics", "DriveBase", "stalled", [([], "bool")]),
]
-2
View File
@@ -1,2 +0,0 @@
version-tag-prefix "@pybricks/ide-docs/v"
version-git-message "@pybricks/ide-docs v%s"
-104
View File
@@ -1,104 +0,0 @@
# Changelog
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
## 2.18.0 - 2024-04-05
### Changed
- Updated docs to v3.5.0b2.
## 2.17.0 - 2024-03-21
### Changed
- Updated docs to v3.5.0b1.
## 2.16.0 - 2024-03-11
### Changed
- Updated docs to v3.4.0.
## 2.15.0 - 2024-03-05
### Changed
- Updated docs to v3.4.0b5.
## 2.14.0 - 2024-01-30
### Changed
- Updated docs to v3.4.0b3.
## 2.13.0 - 2023-11-24
### Changed
- Updated docs to v3.4.0b1.
## 2.12.0 - 2023-11-24
### Changed
- Updated docs to v3.3.0.
## 2.11.0 - 2023-11-20
### Changed
- Updated docs to v3.3.0c1.
## 2.10.0 - 2023-10-26
### Changed
- Updated docs to v3.3.0b9.
## 2.9.0 - 2023-05-16
### Changed
- Updated docs to v3.3.0b5.
## 2.8.0 - 2023-04-21
### Changed
- Updated docs to v3.3.0b4.
## 2.7.0 - 2022-12-20
### Changed
- Updated docs to v3.2.0c2.
## 2.6.0 - 2022-12-09
### Changed
- Updated docs to v3.2.0c1.
## 2.5.0 - 2022-12-02
### Changed
- Updated docs to v3.2.0b6.
## 2.4.0 - 2022-11-11
### Changed
- Updated docs to v3.2.0b5.
## 2.3.0 - 2022-10-21
### Changed
- Updated docs to v3.2.0b4.
## 2.2.0 - 2022-06-02
### Changed
- Updated docs to v3.2.0b1.
## 2.1.0 - 2021-12-16
### Changed
- Updated docs to v3.1.0.
## 2.0.1 - 2021-11-19
### Fixed
- Fixed link to Color Light Matrix page.
## 2.0.0 - 2021-11-19
### Changed
- Changed package directory structure.
- Updated docs to v3.1.0rc1.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@pybricks/ide-docs",
"version": "2.18.0",
"version": "0.0.0",
"description": "Special build of Pybricks API docs for embedding in an IDE.",
"repository": {
"type": "git",
+5
View File
@@ -2,6 +2,11 @@
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
## 1.4.0 - 2022-12-19
### Added
- Added existing NXT and EV3 hub images to published package.
## 1.3.0 - 2022-12-19
### Added
+2 -2
View File
@@ -9,11 +9,11 @@ BUILD_DIR = (pathlib.Path(__file__).parent / "build").resolve()
IMAGE_DIR = (
pathlib.Path(__file__).parent.parent.parent / "doc" / "main" / "diagrams"
).resolve()
HUBS = ["move", "city", "technic", "prime", "essential", "inventor"]
HUBS = ["move", "city", "technic", "prime", "essential", "inventor", "ev3", "nxt"]
package_json = {
"name": "@pybricks/images",
"version": "1.3.0",
"version": "1.4.0",
"description": "Distribution of Pybricks images.",
"license": "MIT",
"repository": {
-2
View File
@@ -1,2 +0,0 @@
version-tag-prefix "@pybricks/jedi/v"
version-git-message "@pybricks/jedi v%s"
-89
View File
@@ -1,89 +0,0 @@
# Changelog
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
## Unreleased
## 1.15.0 - 2024-03-21
### Changed
- Updated `pybricks_jedi` Python package to v1.15.0.
## 1.14.0 - 2024-03-05
### Changed
- Updated `pybricks_jedi` Python package to v1.14.0.
## 1.13.0 - 2024-01-30
### Changed
- Updated `pybricks_jedi` Python package to v1.13.0.
### Changed
- Updated `pybricks_jedi` Python package to v1.12.0.
## 1.12.0 - 2023-11-24
### Changed
- Updated `pybricks_jedi` Python package to v1.12.0.
## 1.11.0 - 2023-11-20
### Changed
- Updated `pybricks_jedi` Python package to v1.11.0.
## 1.10.0 - 2023-10-26
### Changed
- Updated `pybricks_jedi` Python package to v1.10.0.
## 1.9.0 - 2023-05-16
### Changed
- Updated `pybricks_jedi` Python package to v1.9.0.
## 1.8.0 - 2023-04-21
### Changed
- Updated `pybricks_jedi` Python package to v1.8.0.
## 1.7.0 - 2022-12-28
### Changed
- Updated `pybricks_jedi` Python package to v1.7.0.
## 1.6.0 - 2022-12-09
### Changed
- Updated `pybricks_jedi` Python package to v1.6.0.
## 1.5.0 - 2022-12-02
### Changed
- Updated `pybricks_jedi` Python package to v1.5.0.
## 1.4.0 - 2022-12-02
### Changed
- Updated `pybricks_jedi` Python package to v1.4.0.
## 1.3.0 - 2022-11-11
### Changed
- Updated `pybricks_jedi` Python package to v1.3.0.
## 1.2.0 - 2022-10-21
### Changed
- Updated `pybricks_jedi` Python package to v1.2.0.
## 1.0.1 - 2022-09-07
### Fixed
- Fixed exports.
- Fixed missing README and CHANGELOG.
## 1.0.0 - 2022-09-07
### Added
- Added new @pybricks/jedi package.
+22 -13
View File
@@ -8,11 +8,19 @@ import subprocess
import sys
import zipfile
BUILD_DIR = (pathlib.Path(__file__).parent / "build").resolve()
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <version>", file=sys.stderr)
sys.exit(1)
VERSION = sys.argv[1]
ROOT_DIR = pathlib.Path(__file__).parent.resolve()
JEDI_SRC_DIR = (ROOT_DIR / ".." / ".." / "jedi").resolve()
BUILD_DIR = (ROOT_DIR / "build").resolve()
package_json = {
"name": "@pybricks/jedi",
"version": "1.15.0",
"version": VERSION,
"description": "Binary distribution of pybricks-jedi Python package and dependencies for use with Pyodide.",
"repository": {
"type": "git",
@@ -30,7 +38,14 @@ whl_map: dict[str, str] = {}
shutil.rmtree(BUILD_DIR, True)
BUILD_DIR.mkdir()
# download package and dependencies (*.whl files)
# build pybricks-jedi wheel from local source
subprocess.check_call(["poetry", "build", "--format=wheel"], cwd=JEDI_SRC_DIR)
# copy locally built wheel to build dir
for whl in (JEDI_SRC_DIR / "dist").glob("pybricks_jedi-*.whl"):
shutil.copy(whl, BUILD_DIR)
# download transitive dependencies from PyPI, using the local wheel to satisfy pybricks-jedi itself
subprocess.check_call(
[
sys.executable,
@@ -38,7 +53,8 @@ subprocess.check_call(
"pip",
"download",
"--only-binary=any",
"pybricks-jedi==1.15.0",
f"--find-links={BUILD_DIR}",
"pybricks-jedi",
],
cwd=BUILD_DIR,
)
@@ -79,13 +95,8 @@ for whl in BUILD_DIR.glob("*.whl"):
license_identifiers.add(license)
# TODO: The LICENSE workaround for the pybricks-jedi package can be
# dropped after the next release of that package
if whl.name.startswith("pybricks_jedi-"):
LICENSE = (
pathlib.Path(__file__).parent.parent.parent / "jedi" / "LICENSE"
).resolve()
with open(LICENSE) as lf:
with open(JEDI_SRC_DIR / "LICENSE") as lf:
license_text[whl.name] = lf.read()
else:
try:
@@ -126,7 +137,5 @@ with open(BUILD_DIR / "LICENSE", "w") as f:
# copy additional files
ROOT_DIR = (pathlib.Path(__file__).parent).resolve()
for file in "README.md", "CHANGELOG.md":
for file in ("README.md",):
shutil.copy(ROOT_DIR / file, BUILD_DIR / file)
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pybricks"
version = "3.5.0b2"
version = "4.0.0b2"
description = "Documentation and user-API stubs for Pybricks MicroPython"
authors = ["The Pybricks Authors <team@pybricks.com>"]
maintainers = ["Laurens Valk <laurens@pybricks.com>", "David Lechner <david@pybricks.com>" ]
+179 -155
View File
@@ -40,6 +40,8 @@ if TYPE_CHECKING:
class MaybeAwaitableColor(Color, Awaitable[Color]): ...
class MaybeAwaitableBytes(bytes, Awaitable[bytes]): ...
class System:
"""System control actions for a hub."""
@@ -69,32 +71,6 @@ class System:
Stops your program and shuts the hub down."""
def reset_reason(self) -> int:
"""reset_reason() -> int
Finds out how and why the hub (re)booted. This can be useful to
diagnose some problems.
Returns:
* ``0`` if the hub was previously powered off
normally.
* ``1`` if the hub rebooted automatically, like
after a firmware update.
* ``2`` if the hub previously
crashed due to a watchdog timeout, which indicates a firmware
issue.
"""
def name(self) -> str:
"""name() -> str
Gets the hub name. This is the name you see when connecting
via Bluetooth.
Returns:
The hub name.
"""
@overload
def storage(self, offset: int, *, read: int) -> bytes: ...
@@ -131,6 +107,43 @@ class System:
If you try to read or write data outside of the allowed range.
"""
def reset_storage(self) -> None:
"""reset_storage()
Resets all user settings to default values and erases user programs.
"""
def info(self) -> dict:
"""info() -> dict
Gets information about the hub as a dictionary with the following keys:
- ``"name"``: The hub name. This is the name you see when connecting
via Bluetooth.
- ``"reset_reason"``: Why the hub (re)booted. It is ``0`` if the hub
was previously powered off normally. It is ``1`` if the hub rebooted
automatically, like after a firmware update. It is ``2`` if the hub
previously crashed due to a watchdog timeout, which indicates a
firmware issue.
- ``"host_connected_ble"``: ``True`` if the hub is connected to a
computer, tablet, or phone via Bluetooth, and ``False`` otherwise.
- ``"host_connected_usb"``: ``True`` if the hub is connected to a computer
via USB and activated in the app. ``False`` otherwise.
- ``"program_start_type"``: It is ``1`` if the program started
automatically when the hub was powered on. It is ``2`` if the program
was started with the hub buttons. It is ``3`` if the program was
started from your connected computer.
- `"program_id"`: Program (slot) number of the currently running program.
Returns:
A dictionary with system info.
.. versionchanged:: 3.6
The name and reset reason where previously available as separate
methods. Now they are included in the info dictionary. The methods
are still available for backwards compatibility.
"""
class DCMotor:
"""Generic class to control simple motors without rotation sensors, such
@@ -471,6 +484,11 @@ class Motor(DCMotor):
Sets the accumulated rotation angle of the motor to a desired value.
If this motor is also being used by a drive base, its distance and
angle values will also be affected. You might want to
use its :meth:`reset <pybricks.robotics.DriveBase.reset>`
method instead.
Arguments:
angle (Number, deg): Value to which the angle should be reset.
"""
@@ -815,7 +833,7 @@ class LightMatrix:
contents remain unchanged.
Arguments:
top (Side): Which side of the light matrix display is "up" in your
up (Side): Which side of the light matrix display is "up" in your
design. Choose ``Side.TOP``, ``Side.LEFT``, ``Side.RIGHT``,
or ``Side.BOTTOM``.
"""
@@ -1013,34 +1031,67 @@ class SimpleAccelerometer:
"""
class Accelerometer(SimpleAccelerometer):
"""Get measurements from an accelerometer."""
class IMU:
def up(self, calibrated: bool = True) -> Side:
"""up(calibrated=True) -> Side
Checks which side of the hub currently faces upward.
Arguments:
calibrated (bool): Choose ``True`` to use calibrated gyroscope and
accelerometer data to determine which way is up. Choose
``False`` to use raw acceleration values.
Returns:
``Side.TOP``, ``Side.BOTTOM``, ``Side.LEFT``, ``Side.RIGHT``,
``Side.FRONT`` or ``Side.BACK``.
"""
def tilt(self, calibrated: bool = True) -> Tuple[int, int]:
"""tilt(calibrated=True) -> Tuple[int, int]
Gets the pitch and roll angles. This is relative to the
:ref:`user-specified neutral orientation <robotframe>`.
The order of rotation is pitch-then-roll. This is equivalent to a
positive rotation along the robot y-axis and then a positive rotation
along the x-axis.
Arguments:
calibrated (bool): Choose ``True`` to use calibrated gyroscope and
accelerometer data to determine the tilt. Choose ``False``
to use raw acceleration values.
Returns:
Tuple of pitch and roll angles in degrees.
"""
@overload
def acceleration(self, axis: Axis) -> float: ...
def acceleration(self, axis: Axis = None, calibrated: bool = True) -> float: ...
@overload
def acceleration(self) -> Matrix: ...
def acceleration(self, calibrated: bool = True) -> Matrix: ...
def acceleration(self, *args):
"""
acceleration(axis) -> float: mm/
acceleration() -> vector: mm/
acceleration(axis, calibrated=True) -> float: mm/
acceleration(calibrated=True) -> vector: mm/
Gets the acceleration of the device along a given axis in the
:ref:`robot reference frame <robotframe>`.
Arguments:
axis (Axis): Axis along which the acceleration should be
measured.
measured, or ``None`` to get a vector along all axes.
calibrated (bool): Choose ``True`` to use calibrated acceleration
values. Choose ``False`` to use raw acceleration values.
Returns:
Acceleration along the specified axis. If you specify no axis,
this returns a vector of accelerations along all axes.
"""
class IMU(Accelerometer):
def ready(self) -> bool:
"""ready() -> bool
@@ -1068,38 +1119,91 @@ class IMU(Accelerometer):
@overload
def settings(
self,
*,
angular_velocity_threshold: float = None,
acceleration_threshold: float = None,
heading_correction: float = None,
angular_velocity_bias: Tuple[float, float, float] = None,
angular_velocity_scale: Tuple[float, float, float] = None,
acceleration_correction: Tuple[float, float, float, float, float, float] = None,
) -> None: ...
@overload
def settings(self) -> Tuple[float, float]: ...
def settings(
self,
) -> Tuple[
float,
float,
float,
Tuple[float, float, float],
Tuple[float, float, float],
Tuple[float, float, float, float, float, float],
]: ...
def settings(self, *args):
"""
settings(angular_velocity_threshold, acceleration_threshold)
settings() -> Tuple[float, float]
settings(*, angular_velocity_threshold, acceleration_threshold, heading_correction, angular_velocity_bias, angular_velocity_scale, acceleration_correction)
settings() -> Tuple
Configures the IMU settings. If no arguments are given,
this returns the current values.
this returns the current values. Use keyword arguments for each value
to ensure correct behavior because settings may be added or changed in
future releases.
These IMU settings are saved on the hub. They will keep their values
until you change them again. The values will be reset to default values
if you update the hub to a different firmware version or call the
``hub.system.reset_storage`` method.
The ``angular_velocity_threshold`` and ``acceleration_threshold``
define when the hub is considered stationary. If all
measurements stay below these thresholds for one second, the IMU
will recalibrate itself.
In a noisy room with high ambient vibrations (such as a
competition hall), it is recommended to increase the thresholds
will recalibrate itself. In a noisy room with high ambient vibrations (such as a
competition hall), you can increase the thresholds
slightly to give your robot the chance to calibrate.
To verify that your settings are working as expected, test that
the ``stationary()`` method gives ``False`` if your robot is moving,
and ``True`` if it is sitting still for at least a second.
and ``True`` if it is sitting still.
The gyroscope measures how fast the hub rotates to estimate the total
angle. Due to variations in the production process, each
hub consistently reports a different value for a full rotation. For
example, your hub might consistently report `357` degrees for every
`360` degree turn. You can measure this value
with ``hub.imu.rotation(-Axis.Z, calibrated=False)`` and enter it as
the ``heading_correction`` setting. Then, the ``hub.imu.heading()``
method will take it into account going forward, correctly scaling it
to 360 degrees for a full rotation.
Arguments:
angular_velocity_threshold (Number, deg/s): The threshold for
angular velocity. The default value is 1.5 deg/s.
acceleration_threshold (Number, mm/): The threshold for angular
velocity. The default value is 250 mm/.
variations in the angular velocity below which the hub is
considered stationary enough to calibrate.
After a reset the value is 2 deg/s.
acceleration_threshold (Number, mm/): The threshold for
variations in acceleration below which the hub is considered
stationary enough to calibrate. After a reset the value
is 2500 mm/.
heading_correction (Number, deg): Number of degrees
reported by for one full rotation of your robot.
After a reset the value is 360 degrees. This is applied on top
of any scaling that is done by the ``angular_velocity_scale``
setting.
angular_velocity_bias (tuple, deg/s): Initial bias for angular
velocity measurements along x, y, and z immediately after boot.
After a reset the value is (0, 0, 0) deg/s.
angular_velocity_scale (tuple, deg): Scale adjustment for x, y, and
z rotation to account for manufacturing differences. After a
reset the value is (360, 360, 360) deg/s. The correct values
can be obtained using `hub.imu.rotation(Axis.X, calibrated=False)`
and repeating it for each axis.
acceleration_correction (tuple, mm/): Scale adjustment for x, y,
and z gravity magnitude in both directions to account for
manufacturing differences. After a reset the
value is (9806.65, -9806.65, 9806.65, -9806.65, 9806.65, -9806.65) mm/.
The correct values can be
obtained using `hub.imu.acceleration(Axis.X, calibrated=False)`
and repeating it for all axes in both directions.
"""
def heading(self) -> float:
@@ -1112,17 +1216,6 @@ class IMU(Accelerometer):
even as the robot turns more than 180 degrees. It does not wrap around
to -180 like it does in some apps.
.. note:: *For now, this method only keeps track of the heading while
the robot is on a flat surface.*
This means that the value is
no longer correct if you lift it from the table. To solve
this, you can call ``reset_heading`` to reset the heading to
a known value *after* you put it back down. For example, you
could align your robot with the side of the competition table
and reset the heading 90 degrees as the new starting point.
Returns:
Heading angle relative to starting orientation.
@@ -1133,35 +1226,50 @@ class IMU(Accelerometer):
Resets the accumulated heading angle of the robot.
This cannot be called while a drive base is using the gyro to drive or
hold position.
Use :meth:`DriveBase.reset() <pybricks.robotics.DriveBase.reset>`
instead, which will stop the robot and then set the new heading value.
.. versionchanged:: 3.6 Resetting the angle while driving is not allowed. Stop first.
Arguments:
angle (Number, deg): Value to which the heading should be reset.
Raises:
OSError:
There is a drive base that is currently using the gyro.
"""
@overload
def angular_velocity(self, axis: Axis) -> float: ...
def angular_velocity(self, axis: Axis = None, calibrated: bool = True) -> float: ...
@overload
def angular_velocity(self) -> Matrix: ...
def angular_velocity(self, calibrated: bool = True) -> Matrix: ...
def angular_velocity(self, *args):
"""
angular_velocity(axis) -> float: deg/s
angular_velocity() -> vector: deg/s
angular_velocity(axis, calibrated=True) -> float: deg/s
angular_velocity(calibrated=True) -> vector: deg/s
Gets the angular velocity of the device along a given axis in
the :ref:`robot reference frame <robotframe>`.
Arguments:
axis (Axis): Axis along which the angular velocity should be
measured.
measured, or ``None`` to get a vector along all axes.
calibrated (bool): Choose ``True`` to compensate for the estimated
bias and configured scale of the gyroscope. Choose ``False``
to get raw angular velocity values.
Returns:
Angular velocity along the specified axis. If you specify no axis,
this returns a vector of accelerations along all axes.
"""
def rotation(self, axis: Axis) -> float:
def rotation(self, axis: Axis, calibrated: bool = True) -> float:
"""
rotation(axis) -> float: deg
rotation(axis, calibrated=True) -> float: deg
Gets the rotation of the device along a given axis in
the :ref:`robot reference frame <robotframe>`.
@@ -1170,10 +1278,11 @@ class IMU(Accelerometer):
axis. For general three-dimensional motion, use the
``orientation()`` method instead.
The value starts counting from ``0`` when you initialize this class.
Arguments:
axis (Axis): Axis along which the rotation should be measured.
calibrated (bool): Choose ``True`` to compensate for configured
scale of the gyroscope. Choose ``False`` to get unscaled values.
Returns:
The rotation angle.
"""
@@ -1188,10 +1297,8 @@ class IMU(Accelerometer):
It returns a rotation matrix whose columns represent the ``X``, ``Y``,
and ``Z`` axis of the robot.
.. note:: This method is not yet implemented.
Returns:
The rotation matrix.
The 3x3 rotation matrix.
"""
@@ -1326,86 +1433,3 @@ class AmbientColorSensor(CommonColorSensor):
Measured color. The color is described by a hue (0--359), a
saturation (0--100), and a brightness value (0--100).
"""
class BLE:
"""
Bluetooth Low Energy.
.. versionadded:: 3.3
"""
def broadcast(self, data: Union[bool, int, float, str, bytes]) -> None:
"""broadcast(data)
Starts broadcasting the given data on
the ``broadcast_channel`` you selected when initializing the hub.
Data may be of type ``int``, ``float``, ``str``, ``bytes``,
``True``, or ``False``, or a list thereof.
Choose ``None`` to stop broadcasting. This helps improve performance
when you don't need the broadcast feature, especially when observing
at the same time.
The total data size is quite limited (26 bytes). ``True`` and
``False`` take 1 byte each. ``float`` takes 5 bytes. ``int`` takes 2 to
5 bytes depending on how big the number is. ``str`` and ``bytes`` take
the number of bytes in the object plus one extra byte.
When multitasking, only one task can broadcast at a time. To broadcast
information from multiple tasks (or block stacks), you could use a
dedicated separate task that broadcast new values when one or more
variables change.
Args:
data: The value or values to be broadcast.
.. versionadded:: 3.3
"""
def observe(
self, channel: int
) -> Optional[Tuple[Union[bool, int, float, str, bytes], ...]]:
"""observe(channel) -> bool | int | float | str | bytes | tuple | None
Retrieves the last observed data for a given channel.
Receiving data is more reliable when the hub is not connected
to a computer or other devices at the same time.
Args:
channel (int): The channel to observe (0 to 255).
Returns:
The received data in the same format as it was sent, or ``None``
if no recent data is available.
.. versionadded:: 3.3
"""
def signal_strength(self, channel: int) -> int:
"""signal_strength(channel) -> int: dBm
Gets the average signal strength in dBm for the given channel.
This indicates how near the broadcasting device is. Nearby devices
may have a signal strength around -40 dBm, while far away devices
might have a signal strength around -70 dBm.
Args:
channel (int): The channel number (0 to 255).
Returns:
The signal strength or ``-128`` if there is no recent observed data.
.. versionadded:: 3.3
"""
def version(self) -> str:
"""version() -> str
Gets the firmware version from the Bluetooth chip.
.. versionadded:: 3.3
"""
+4 -4
View File
@@ -3,7 +3,7 @@
"""LEGO® MINDSTORMS® EV3 motors and sensors."""
from typing import Optional, Tuple, List
from typing import Optional, Tuple, List, Set
from . import _common
from .parameters import (
@@ -57,7 +57,7 @@ class ColorSensor:
Returns:
``Color.BLACK``, ``Color.BLUE``, ``Color.GREEN``,
``Color.YELLOW``, ``Color.RED``, ``Color.WHITE``, ``Color.BROWN``,
or ``None`` if no color is detected.
or ``Color.NONE`` if no color is detected.
"""
@@ -134,8 +134,8 @@ class InfraredSensor:
a tuple of (``None``, ``None``) if no remote is detected.
"""
def buttons(self, channel: int) -> List[_Button]:
"""buttons(channel) -> List[Button]
def buttons(self, channel: int) -> Set[_Button]:
"""buttons(channel) -> Set[Button]
Checks which buttons on the infrared remote are pressed.
+9 -75
View File
@@ -3,8 +3,6 @@
"""LEGO® Programmable Hubs."""
from typing import Sequence
from . import _common
from .ev3dev import _speaker
from .media.ev3dev import Image as _Image
@@ -41,28 +39,19 @@ class MoveHub:
imu = _common.SimpleAccelerometer()
system = _common.System()
buttons = _common.Keypad([_Button.CENTER])
ble = _common.BLE()
def __init__(
self, broadcast_channel: int = 0, observe_channels: Sequence[int] = []
self,
top_side: Axis = Axis.Z,
front_side: Axis = Axis.X,
):
"""MoveHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
"""MoveHub(top_side=Axis.Z, front_side=Axis.X)
Arguments:
top_side (Axis): The axis that passes through the *top side* of
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
broadcast_channel:
A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
will use. Default is channel 0.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
.. versionchanged:: 3.3
Added *broadcast_channel* and *observe_channels* arguments.
"""
@@ -75,25 +64,9 @@ class CityHub:
light = _common.ColorLight()
system = _common.System()
buttons = _common.Keypad([_Button.CENTER])
ble = _common.BLE()
def __init__(
self, broadcast_channel: int = 0, observe_channels: Sequence[int] = []
):
"""CityHub(broadcast_channel=0, observe_channels=[])
Arguments:
broadcast_channel:
A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
will use. Default is channel 0.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
.. versionchanged:: 3.3
Added *broadcast_channel* and *observe_channels* arguments.
"""
def __init__(self):
"""CityHub()"""
class TechnicHub:
@@ -106,16 +79,13 @@ class TechnicHub:
imu = _common.IMU()
system = _common.System()
buttons = _common.Keypad([_Button.CENTER])
ble = _common.BLE()
def __init__(
self,
top_side: Axis = Axis.Z,
front_side: Axis = Axis.X,
broadcast_channel: int = 0,
observe_channels: Sequence[int] = [],
):
"""TechnicHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
"""TechnicHub(top_side=Axis.Z, front_side=Axis.X)
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design <robotframe>` by saying in which
@@ -127,16 +97,6 @@ class TechnicHub:
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
broadcast_channel:
A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
will use. Default is channel 0.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
.. versionchanged:: 3.3
Added *broadcast_channel* and *observe_channels* arguments.
"""
@@ -151,16 +111,13 @@ class EssentialHub:
light = _common.ColorLight()
imu = _common.IMU()
system = _common.System()
ble = _common.BLE()
def __init__(
self,
top_side: Axis = Axis.Z,
front_side: Axis = Axis.X,
broadcast_channel: int = 0,
observe_channels: Sequence[int] = [],
):
"""EssentialHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
"""EssentialHub(top_side=Axis.Z, front_side=Axis.X)
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design <robotframe>` by saying in which
@@ -172,16 +129,6 @@ class EssentialHub:
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
broadcast_channel:
A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
will use. Default is channel 0.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
.. versionchanged:: 3.3
Added *broadcast_channel* and *observe_channels* arguments.
"""
pass
@@ -206,16 +153,13 @@ class PrimeHub:
speaker = _common.Speaker()
imu = _common.IMU()
system = _common.System()
ble = _common.BLE()
def __init__(
self,
top_side: Axis = Axis.Z,
front_side: Axis = Axis.X,
broadcast_channel: int = 0,
observe_channels: Sequence[int] = [],
):
"""PrimeHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
"""PrimeHub(top_side=Axis.Z, front_side=Axis.X)
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design <robotframe>` by saying in which
@@ -227,16 +171,6 @@ class PrimeHub:
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
broadcast_channel:
A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
will use. Default is channel 0.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
.. versionchanged:: 3.3
Added *broadcast_channel* and *observe_channels* arguments.
"""
+356 -114
View File
@@ -5,13 +5,13 @@
from __future__ import annotations
from typing import Dict, Tuple, Optional, overload, TYPE_CHECKING
from typing import Tuple, Optional, overload, TYPE_CHECKING
from . import _common
from .parameters import Port as _Port
if TYPE_CHECKING:
from ._common import MaybeAwaitable, MaybeAwaitableTuple
from ._common import MaybeAwaitable, MaybeAwaitableBytes, MaybeAwaitableTuple
from .parameters import Number
@@ -25,13 +25,21 @@ class PUPDevice:
port (Port): Port to which the device is connected.
"""
def info(self) -> Dict[str, str]:
def info(self) -> dict:
"""info() -> Dict
Gets information about the device.
For passive devices (such as DC motors or lights), returns a
dictionary with only the ``id`` key.
For UART devices, returns a dictionary with an ``id`` key and a
``modes`` key. The ``modes`` value is a tuple of tuples, one per
mode, each containing the mode name, number of values, and data
type.
Returns:
Dictionary with information, such as the device ``id``.
Dictionary with device information.
"""
def read(self, mode: int) -> MaybeAwaitableTuple:
@@ -39,89 +47,86 @@ class PUPDevice:
Reads values from a given mode.
For passive touch sensors, this returns a single boolean value
indicating whether the sensor is pressed, regardless of the
``mode`` argument.
Raises an error for other passive devices such as DC motors and
lights, which do not support reading.
Arguments:
mode (int): Device mode.
Returns:
Values read from the sensor.
Values read from the device.
Raises:
OSError: If the device is a passive device that does not
support reading (e.g. a DC motor or light).
"""
def write(self, mode: int, data: Tuple) -> MaybeAwaitable:
"""write(mode, data)
Writes values to the sensor. Only selected sensors and modes support
this.
Writes values to the device. Only selected UART devices and modes
support this.
Arguments:
mode (int): Device mode.
data (tuple): Values to be written.
data (tuple): Values to be written. The number of values and
their types must match what the device expects for the
given mode.
Raises:
OSError: If the device is a passive device that does not
support writing.
ValueError: If the mode is invalid, the mode is not writable,
the number of values does not match, or a value is out of
range for its data type.
"""
def reset(self) -> None:
"""reset()
Resets the UART device. After this, it should automatically synchronize
and be ready for use after a few seconds. This is useful to forcefully
re-trigger what such a sensor does when plugged in.
Raises:
OSError: If the device is a passive device that does not
support reset.
"""
class LUMPDevice:
"""Devices using the LEGO UART Messaging Protocol."""
class LUMPDevice(PUPDevice):
"""Devices using the LEGO UART Messaging Protocol.
def __init__(self, port: _Port):
"""LUMPDevice(port)
See the equivalent :class:`PUPDevice() <pybricks.iodevices.PUPDevice>` for
a description of available methods.
Arguments:
port (Port): Port to which the device is connected.
"""
def read(self, mode: int) -> MaybeAwaitableTuple:
"""read(mode) -> Tuple
Reads values from a given mode.
Arguments:
mode (int): Device mode.
Returns:
Values read from the sensor.
"""
On EV3, this class provides access to UART devices only. You can use other
classes to interact with passive devices.
"""
class DCMotor(_common.DCMotor):
"""DC Motor for LEGO® MINDSTORMS EV3."""
class Ev3devSensor:
"""Read values of an ev3dev-compatible sensor."""
sensor_index: int
"""Index of the ev3dev sysfs `lego-sensor`_ class."""
port_index: int
"""Index of the ev3dev sysfs `lego-port`_ class."""
def __init__(self, port: _Port):
"""Ev3devSensor(port)
Arguments:
port (Port): Port to which the device is connected.
"""
def read(self, mode: str) -> MaybeAwaitableTuple:
"""read(mode) -> Tuple
Reads values at a given mode.
Arguments:
mode (str): `Mode name`_.
Returns:
values read from the sensor.
"""
class AnalogSensor:
"""Generic or custom analog sensor."""
def __init__(self, port: _Port):
"""AnalogSensor(port)
def __init__(self, port: _Port, custom: bool = False):
"""AnalogSensor(port, custom=False)
Arguments:
port (Port): Port to which the sensor is connected.
custom (bool): Set to ``True`` if you are using a custom analog
sensor.
Raises:
OSError: If no standard LEGO analog sensor is
detected on the port. Only applies if ``custom=False``.
"""
def voltage(self) -> int:
@@ -139,10 +144,15 @@ class AnalogSensor:
Measures resistance.
This value is only meaningful if the analog device is a passive load
such as a resistor or thermistor.
such as a resistor or thermistor. It is calculated assuming a 10
internal pull-up resistor forming a voltage divider.
If the circuit is open (no load connected), the maximum integer value
is returned.
Returns:
Resistance of the analog device.
Resistance of the analog device, or the maximum integer value
if the circuit is open.
"""
def active(self) -> None:
@@ -171,58 +181,125 @@ class AnalogSensor:
class I2CDevice:
"""Generic or custom I2C device."""
"""Generic or custom I2C device.
def __init__(self, port: _Port, address: int):
"""I2CDevice(port, address)
Note: Use the ``power_pin`` option at your own risk. Applying power to the
pins can damage your hub or device if you are not careful. When you use
this option, you will be prompted to confirm that you understand the risks.
"""
def __init__(
self,
port: _Port,
address: int,
custom: bool = False,
power_pin: int = 0,
nxt_quirk: bool = False,
):
"""I2CDevice(port, address, custom=False, power_pin=0, nxt_quirk=False)
Arguments:
port (Port): Port to which the device is connected.
address(int): I2C address of the client device. See
address (int): I2C address of the client device. See
:ref:`I2C Addresses <i2caddress>`.
custom (bool): Set to ``True`` if you are using a custom I2C device.
power_pin (int): Power requirements for the device. Use
``0`` (default) for no power on the pins. On NXT and EV3, use ``1``
to apply battery power to pin 1. Other pins are not supported.
nxt_quirk (bool): Set to ``True`` for older NXT I2C sensors that
need slower compatibility timing to communicate reliably,
such as the old NXT Ultrasonic Sensor.
"""
def read(self, reg: Optional[int], length: Optional[int] = 1) -> bytes:
"""read(reg, length=1)
@overload
def read(
self, reg: Optional[int] = None, length: int = 1
) -> MaybeAwaitableBytes: ...
Reads bytes, starting at a given register.
@overload
def read(
self, reg: Optional[int] = None, length: int = 1, map: callable = ...
) -> MaybeAwaitable: ...
def read(
self, reg: Optional[int] = None, length: int = 1, map=None
) -> MaybeAwaitableBytes:
"""read(reg=None, length=1) -> bytes
read(reg=None, length=1, map=callable) -> Any
Reads bytes starting at a given register.
Arguments:
reg (int): Register at which to begin
reading: 0--255 or 0x00--0xFF.
reg (int): Register at which to begin reading: 0--255 or
0x00--0xFF. Use ``None`` to read without writing a register
address first.
length (int): How many bytes to read.
map (callable): Optional callable to convert the returned bytes.
If given, it is called with the bytes as its argument and its
return value is returned instead.
Returns:
Bytes returned from the device.
Bytes returned from the device, or the return value of ``map``
if a callable was provided.
"""
def write(self, reg: Optional[int], data: Optional[bytes] = None) -> None:
"""write(reg, data=None)
def write(
self, reg: Optional[int] = None, data: Optional[bytes] = None
) -> MaybeAwaitable:
"""write(reg=None, data=None)
Writes bytes, starting at a given register.
Writes bytes, optionally starting at a given register.
Arguments:
reg (int): Register at which to begin
writing: 0--255 or 0x00--0xFF.
data (bytes): Bytes to be written.
reg (int): Register at which to begin writing: 0--255 or
0x00--0xFF. Use ``None`` to write without a register prefix.
data (bytes): Bytes to be written. Use ``None`` to write nothing
after the register.
Raises:
ValueError: If ``reg`` is given and ``data`` is more than 32 bytes.
To write more data, omit the ``reg`` argument and include the
register as the first byte of ``data``.
"""
class UARTDevice:
"""Generic UART device."""
"""Generic UART device.
def __init__(self, port: _Port, baudrate: int, timeout: Optional[int] = None):
"""UARTDevice(port, baudrate, timeout=None)
Note: Use the ``power_pin`` option at your own risk. Applying power to the
pins can damage your hub or device if you are not careful. When you use
this option, you will be prompted to confirm that you understand the risks.
"""
def __init__(
self,
port: _Port,
baudrate: int = 115200,
timeout: Optional[int] = None,
power_pin: int = 0,
):
"""UARTDevice(port, baudrate=115200, timeout=None, power_pin=0)
Arguments:
port (Port): Port to which the device is connected.
port (Port): Port to which the device is connected. On Powered UP
hubs, all ports are supported. On EV3, only the sensor ports
are supported.
baudrate (int): Baudrate of the UART device.
timeout (Number, ms): How long to wait
during ``read`` before giving up. If you choose ``None``,
it will wait forever.
timeout (Number, ms): How long to wait during ``read`` and
``write`` before giving up. If you choose ``None``, it will
wait forever.
power_pin (int): Power requirements for the device. Use ``0``
(default) for no power on the pins. On Powered UP hubs, use
``1`` or ``2`` for pin 1 or 2, respectively. This will apply
battery power to the pin, equivalent to powering a motor.
On EV3, use ``1`` to apply battery power to pin 1, though only
minimal current is available.
Raises:
ValueError: If ``timeout`` is 0 or negative.
"""
def read(self, length: int = 1) -> bytes:
def read(self, length: int = 1) -> MaybeAwaitableBytes:
"""read(length=1) -> bytes
Reads a given number of bytes from the buffer.
@@ -232,28 +309,38 @@ class UARTDevice:
exception is raised.
Arguments:
length (int): How many bytes to read.
length (int): How many bytes to read. Must be at least 1.
Returns:
Bytes returned from the device.
Raises:
ValueError: If ``length`` is less than 1.
OSError: If the read takes longer than ``timeout``.
"""
def read_all(self) -> bytes:
"""read_all() -> bytes
Reads all bytes from the buffer.
Reads all bytes currently in the buffer. Returns immediately without
waiting, even if the buffer is empty.
Returns:
Bytes returned from the device.
Bytes currently in the buffer, or an empty bytes object if there
is nothing to read.
"""
def write(self, data: bytes) -> None:
def write(self, data: bytes) -> MaybeAwaitable:
"""write(data)
Writes bytes.
Writes bytes to the device.
Arguments:
data (bytes): Bytes to be written.
Raises:
TypeError: If ``data`` is not ``bytes``, ``bytearray``, or ``str``.
OSError: If the write takes longer than ``timeout``.
"""
def waiting(self) -> int:
@@ -265,23 +352,57 @@ class UARTDevice:
Number of bytes in the buffer.
"""
def set_baudrate(self, baudrate: int) -> None:
"""set_baudrate(baudrate)
Changes the baud rate of the UART device.
Arguments:
baudrate (int): Not all values may be supported.
Raises:
ValueError: If ``baudrate`` is less than 1.
"""
def wait_until(self, pattern: bytes) -> MaybeAwaitable:
"""wait_until(pattern)
Waits until a specific byte sequence is received. Bytes that do not
match the pattern are discarded.
Arguments:
pattern (bytes): Byte sequence to wait for. Must not be empty.
Raises:
ValueError: If ``pattern`` is empty.
OSError: If this method is already in progress.
"""
def clear(self) -> None:
"""clear()
Empties the buffer."""
Empties the receive buffer."""
class LWP3Device:
"""
Connects to a hub running official LEGO firmware using the
`LEGO Wireless Protocol v3`_
`LEGO Wireless Protocol v3`_.
.. _`LEGO Wireless Protocol v3`:
https://lego.github.io/lego-ble-wireless-protocol-docs/
"""
def __init__(self, hub_kind: int, name: str = None, timeout: int = 10000):
"""LWP3Device(hub_kind, name=None, timeout=10000)
def __init__(
self,
hub_kind: int,
name: str = None,
timeout: int = 10000,
pair: bool = False,
num_notifications: int = 8,
connect: bool = True,
):
"""LWP3Device(hub_kind, name=None, timeout=10000, pair=False, num_notifications=8, connect=True)
Arguments:
hub_kind (int):
@@ -292,12 +413,35 @@ class LWP3Device:
timeout (int):
The time, in milliseconds, to wait for a connection before
raising an exception.
pair (bool): Whether to attempt pairing for a secure connection.
This is required for some newer hubs.
num_notifications (int): Number of incoming messages from the remote
hub to store before discarding older messages.
connect (bool): Choose ``False`` to skip connecting.
``connect()`` can be called later to connect.
.. versionchanged:: 3.6
Added ``pair`` parameter.
.. versionchanged:: 3.7
Added ``num_notifications`` parameter.
.. _`hub type identifier`:
https://github.com/pybricks/technical-info/blob/master/assigned-numbers.md#hub-type-ids
"""
def connect(self) -> MaybeAwaitable:
"""connect()
Connects to the device. Only needed if you disconnected or initialized
with ``connect=False``.
Raises:
OSError: If the connection attempt fails or times out.
"""
@overload
def name(self, name: str) -> MaybeAwaitable: ...
@@ -313,6 +457,9 @@ class LWP3Device:
Arguments:
name (str): New Bluetooth name of the device. If no name is given,
this method returns the current name.
Raises:
OSError: If the device is not connected.
"""
def write(self, buf: bytes) -> MaybeAwaitable:
@@ -321,25 +468,36 @@ class LWP3Device:
Sends a message to the remote hub.
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:
"""read() -> bytes
def read(self) -> bytes | None:
"""read() -> bytes | None
Retrieves the most recent message received from the remote hub.
Retrieves the oldest buffered message received from the remote hub.
If a message has not been received since the last read, the method will
block until a message is received.
If all buffered messages have already been read, this returns ``None``.
Returns:
The raw binary message.
The oldest raw binary message or ``None`` if there are no more messages.
.. versionchanged:: 3.7
Now supports reading multiple buffered messages instead of blocking
until one new message was received.
"""
def disconnect(self) -> MaybeAwaitable:
"""disconnect()
Disconnects the remote LWP3Device from the hub.
Disconnects the device.
Raises:
OSError: If disconnecting fails.
"""
@@ -355,27 +513,95 @@ class XboxController:
buttons = _common.Keypad([])
def __init__(self):
""""""
def __init__(
self,
joystick_deadzone: int = 10,
name: Optional[str] = None,
timeout: int = 10000,
connect: bool = True,
):
"""__init__(joystick_deadzone=10, name=None, timeout=10000, connect=True)
Arguments:
joystick_deadzone (Number, %): Joystick deadzone (0 to 100). Values
below this threshold in both axes will be reported as 0 to
prevent stick drift.
name (str): The Bluetooth name of the Xbox controller to connect to,
or ``None`` to connect to any available controller.
timeout (Number, ms): How long to wait for a connection before
giving up. Choose ``None`` to wait indefinitely.
connect (bool): Choose ``False`` to skip connecting to the controller.
``connect()`` can be called later to connect.
"""
def connect(self) -> MaybeAwaitable:
"""connect()
Connects to the Xbox controller. Only needed if you disconnected or
initialized the controller with ``connect=False``.
"""
def disconnect(self) -> MaybeAwaitable:
"""disconnect()
Disconnects the Xbox controller.
"""
def name(self) -> str:
"""name() -> str
Gets the Bluetooth name of the connected controller.
Returns:
Bluetooth name of the controller.
Raises:
OSError: If the controller is not connected.
"""
def state(self) -> Tuple:
"""state() -> Tuple
Gets all raw controller input values as a single tuple. This gives
access to values not exposed by the other methods.
The joystick axes (x, y, z, rz) are centered at 0. The trigger axes
are raw 10-bit values (0-1023).
Returns:
Tuple of ``(x, y, z, rz, left_trigger, right_trigger, dpad,
buttons, upload, profile, trigger_switches, paddles)``.
Raises:
OSError: If the controller is not connected.
"""
def joystick_left(self) -> Tuple[int, int]:
"""joystick_left() -> Tuple
Gets the left joystick position as percentages between -100%
and 100%. The center position is (0, 0).
and 100%. The center position is (0, 0). A square deadzone is applied:
if both axes are within the deadzone, both are reported as 0.
Returns:
Tuple of X (horizontal) and Y (vertical) position.
Raises:
OSError: If the controller is not connected.
"""
def joystick_right(self) -> Tuple[int, int]:
"""joystick_right() -> Tuple
Gets the right joystick position as percentages between -100%
and 100%. The center position is (0, 0).
and 100%. The center position is (0, 0). A square deadzone is applied:
if both axes are within the deadzone, both are reported as 0.
Returns:
Tuple of X (horizontal) and Y (vertical) position.
Raises:
OSError: If the controller is not connected.
"""
def triggers(self) -> Tuple[int, int]:
@@ -386,6 +612,9 @@ class XboxController:
Returns:
Tuple of left and right trigger positions.
Raises:
OSError: If the controller is not connected.
"""
def dpad(self) -> int:
@@ -402,6 +631,9 @@ class XboxController:
Returns:
Direction-pad position, indicating a direction.
Raises:
OSError: If the controller is not connected.
"""
def profile(self) -> int:
@@ -412,6 +644,9 @@ class XboxController:
Returns:
Profile number.
Raises:
OSError: If the controller is not connected.
"""
def rumble(
@@ -426,27 +661,34 @@ class XboxController:
Makes the builtin actuators rumble, creating force feedback.
If you give a single ``power`` value, the left and right main actuators
will both rumble with that power. For more fine-grained control, set
``power`` as a tuple of four values, which control the left main
actuator, right main actuator, left trigger actuator, and the right
trigger actuator, respectively. For example, ``power=(0, 0, 100, 0)``
makes the left trigger rumble at full power.
will both rumble with that power while the trigger actuators stay off.
For more fine-grained control, set ``power`` as a tuple of four values,
which control the left main actuator, right main actuator, left trigger
actuator, and the right trigger actuator, respectively. For example,
``power=(0, 0, 100, 0)`` makes the left trigger rumble at full power.
The rumble runs in the background while your program continues. To
make your program wait, just pause the program for a matching duration.
For one rumble, this equals ``duration``. For multiple rumbles, this
equals ``count * (duration + delay)``.
This method does nothing if all actuator powers are zero, if
``duration`` is zero, or if ``count`` is less than 1.
Arguments:
power (Number, % or tuple): Rumble power.
duration (Number, ms): Rumble duration.
count (int): Rumble count.
delay (Number, ms): Delay before each rumble. Only if ``count > 1``.
power (Number, % or tuple): Rumble power. A single value applies
to both main actuators (0-100%). A tuple applies individually
to (left handle, right handle, left trigger, right trigger).
duration (Number, ms): Duration of each rumble. Capped at 2500 ms.
count (int): Number of rumbles (0-100).
delay (Number, ms): Delay before each rumble. Only used if
``count > 1``. Capped at 2500 ms.
"""
# hide from jedi
if TYPE_CHECKING:
del MaybeAwaitable
del MaybeAwaitableBytes
del MaybeAwaitableTuple
del Number
+241 -9
View File
@@ -1,29 +1,170 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2026 The Pybricks Authors
"""
Classes to exchange messages between EV3 bricks.
Classes to send and receive messages from another device.
"""
from __future__ import annotations
from typing import abstractmethod, TypeVar, Optional, Callable, Generic
from typing import (
abstractmethod,
Callable,
Generic,
Iterable,
List,
Optional,
overload,
Sequence,
Tuple,
TYPE_CHECKING,
TypeVar,
Union,
)
if TYPE_CHECKING:
from ._common import (
MaybeAwaitable,
)
T = TypeVar("T")
class BLERadio:
"""
Send and receive messages without a connection using Bluetooth Low Energy.
.. versionadded:: 4.0
This used to be part of each hub class.
"""
def __init__(
self,
broadcast_channel: Optional[int] = None,
observe_channels: Sequence[int] = [],
):
"""BLERadio(broadcast_channel=None, observe_channels=[])
Arguments:
broadcast_channel:
Channel number (0 to 255) used to broadcast data.
Choose ``None`` when not using broadcasting.
observe_channels:
A list of channels to listen to when ``hub.ble.observe()`` is
called. Listening to more channels requires more memory.
Default is an empty list (no channels).
"""
@overload
def broadcast(self, data: None) -> MaybeAwaitable: ...
@overload
def broadcast(
self, data: Iterable[Union[bool, int, float, str, bytes]]
) -> MaybeAwaitable: ...
@overload
def broadcast(
self, data: Union[bool, int, float, str, bytes]
) -> MaybeAwaitable: ...
def broadcast(self, data: object) -> MaybeAwaitable:
"""broadcast(data)
Starts broadcasting the given data on the previously selected
``broadcast_channel``.
Data may be of type ``int``, ``float``, ``str``, ``bytes``,
``True``, or ``False``. It can also be a list or tuple of these.
Choose ``None`` to stop broadcasting. This helps improve performance
when you don't need the broadcast feature, especially when observing
at the same time.
The total data size is quite limited (26 bytes). ``True`` and
``False`` take 1 byte each. ``float`` takes 5 bytes. ``int`` takes 2 to
5 bytes depending on how big the number is. ``str`` and ``bytes`` take
the number of bytes in the object plus one extra byte.
When multitasking, only one task can broadcast at a time. To broadcast
information from multiple tasks (or block stacks), you could use a
dedicated separate task that broadcast new values when one or more
variables change.
Args:
data: The value or values to be broadcast.
Raises:
RuntimeError: If no ``broadcast_channel`` was configured.
ValueError: If the encoded data exceeds 26 bytes.
TypeError: If ``data`` contains a value that is not ``bool``,
``int``, ``float``, ``str``, or ``bytes``.
"""
def observe(self, channel: int) -> Optional[
Union[
Tuple[Union[bool, int, float, str, bytes], ...],
Union[bool, int, float, str, bytes],
]
]:
"""observe(channel) -> bool | int | float | str | bytes | tuple | None
Retrieves the last observed data for a given channel.
Receiving data is more reliable when the hub is not connected
to a computer or other devices at the same time.
Args:
channel (int): The channel to observe. Must be one of the channels
given to ``observe_channels`` when creating this object.
Returns:
The received data in the same format as it was sent, or ``None``
if no data has been received within the last second.
Raises:
ValueError: If ``channel`` was not in ``observe_channels``.
"""
def signal_strength(self, channel: int) -> int:
"""signal_strength(channel) -> int: dBm
Gets the average signal strength in dBm for the given channel.
This indicates how near the broadcasting device is. Nearby devices
may have a signal strength around -40 dBm, while far away devices
might have a signal strength around -70 dBm.
Args:
channel (int): The channel number. Must be one of the channels
given to ``observe_channels`` when creating this object.
Returns:
The signal strength, or ``-128`` if no data has been received
within the last second.
Raises:
ValueError: If ``channel`` was not in ``observe_channels``.
"""
def version(self) -> str:
"""version() -> str
Gets the firmware version from the Bluetooth chip.
"""
class Connection:
@abstractmethod
def read_from_mailbox(self, name: str) -> bytes:
...
def read_from_mailbox(self, name: str) -> bytes: ...
@abstractmethod
def send_to_mailbox(self, name: str, data: bytes) -> None:
...
def send_to_mailbox(self, name: str, data: bytes) -> None: ...
@abstractmethod
def wait_for_mailbox_update(self, name: str) -> None:
...
def wait_for_mailbox_update(self, name: str) -> None: ...
class Mailbox(Generic[T]):
@@ -231,3 +372,94 @@ class BluetoothMailboxClient:
"""close()
Closes all connections."""
class AppData:
"""
Exchange raw data with the Pybricks Code host application over USB or
Bluetooth. This is used by the smart sensor features like the vision
processors.
Each processor has on emode and produces a fixed amount of data. These are
continuously sent to the hub as they change. The user code can read these
buffered values at any time without blocking. All values are initially zero.
From the hub's perspective, writing back to the host is an awaitable operation.
Can be used to configure modes and mode settings.
Only one instance may exist at a time. Must be created during program
initialization. After that, all methods may be used while multi-tasking.
"""
def __init__(self, modes: List[Tuple[int, int]]):
"""AppData(modes)
Arguments:
modes:
A list of ``(mode, size)`` tuples, where ``mode`` is a mode
number (0 to 255) and ``size`` is the number of bytes to
allocate for that mode's receive buffer. Mode numbers must be
unique. The list is sorted by mode number automatically.
Raises:
RuntimeError: If an ``AppData`` instance already exists.
TypeError: If ``modes`` is not a list, or if any element is not a
``(mode, size)`` tuple with a mode value of 0 to 255.
ValueError: If any mode number appears more than once.
"""
def get_bytes(self, mode: int, index: Optional[int] = None) -> Union[bytes, int]:
"""get_bytes(mode, index=None) -> bytes | int
Gets data received from the host for the given mode.
Args:
mode (int): The mode number to read.
index (int): If given, returns the single byte at this position
within the mode's buffer as an integer. Otherwise returns
the entire mode buffer as ``bytes``.
Returns:
All received bytes for the mode, or a single byte as an integer
if ``index`` is given.
Raises:
ValueError: If ``mode`` was not configured, or if ``index`` is
out of range.
"""
def write_bytes(self, data: bytes) -> MaybeAwaitable:
"""write_bytes(data)
Sends raw bytes to the host application.
Args:
data (bytes): The data to send.
"""
def configure(self, mode: int, parameter: int, value: bytes) -> MaybeAwaitable:
"""configure(mode, parameter, value)
Sends a configuration command to the host for the given mode.
This is a wrapper around :meth:`write_bytes`. It prepends a
``[0x01, mode, parameter]`` header to configure mode settings.
Args:
mode (int): The mode number to configure.
parameter (int): The parameter identifier within the mode.
value (bytes): The configuration value to send.
"""
def close(self) -> None:
"""close()
Deactivates the data callback and releases the receive buffer.
This is also called automatically when the object is garbage collected.
"""
if TYPE_CHECKING:
del MaybeAwaitable
del T
+20 -2
View File
@@ -112,14 +112,26 @@ class Color:
The brightness value.
"""
def __setattr__(self, key, value):
if key not in ("h", "s", "v"):
raise AttributeError("Can't modify unknown attribute: " + key)
if hasattr(self, key): # immutable after __init__
raise AttributeError("Can't modify immutable attribute: " + key)
super().__setattr__(key, value)
def __iter__(self):
"""Allows unpacking of the Color instance into h, s, and v."""
return iter((self.h, self.s, self.v))
def __repr__(self):
return "Color(h={}, s={}, v={})".format(self.h, self.s, self.v)
def __eq__(self, other: Color) -> bool: ...
def __eq__(self, other: Color) -> bool:
return self.h == other.h and self.s == other.s and self.v == other.v
def __mul__(self, scale: float) -> Color:
v = max(0, min(self.v * scale, 100))
return Color(self.h, self.s, int(v), self.name)
return Color(self.h, self.s, int(v))
def __rmul__(self, scale: float) -> Color:
return self.__mul__(scale)
@@ -130,6 +142,12 @@ class Color:
def __floordiv__(self, scale: int) -> Color:
return self.__mul__(1 / scale)
def __lshift__(self, shift: int) -> Color:
return self.__rshift__(-shift)
def __rshift__(self, shift: int) -> Color:
return Color((self.h + shift) % 360, self.s, self.v)
Color.NONE = Color(0, 0, 0)
Color.BLACK = Color(0, 0, 10)
+227 -25
View File
@@ -5,9 +5,10 @@
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 .iodevices import LWP3Device
from .parameters import Button, Color, Direction
if TYPE_CHECKING:
@@ -86,15 +87,19 @@ class Motor(_common.Motor):
Sets the accumulated rotation angle of the motor to a desired value.
If you don't specify an angle, the absolute angle
will be used if your motor supports it.
If this motor is also being used by a drive base, its distance and
angle values will also be affected. You might want to
use its :meth:`reset <pybricks.robotics.DriveBase.reset>`
method instead.
Arguments:
angle (Number, deg): Value to which the angle should be reset.
Choose ``None`` to reset it to the absolute
value of the motor.
"""
class Remote:
class Remote(LWP3Device):
"""LEGO® Powered Up Bluetooth Remote Control."""
light = _common.ExternalColorLight()
@@ -111,42 +116,238 @@ class Remote:
)
address: Union[str, None]
def __init__(self, name: Optional[str] = None, timeout: int = 10000):
"""Remote(name=None, timeout=10000)
When you instantiate this class, the hub will search for a remote
and connect automatically.
The remote must be on and ready for a connection, as indicated by a
white blinking light.
def __init__(
self,
name: Optional[str] = None,
timeout: int = 10000,
connect: bool = True,
):
"""Remote(name=None, timeout=10000, connect=True)
Arguments:
name (str): Bluetooth name of the remote. If no name is given,
the hub connects to the first remote that it finds.
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
def name(self) -> str: ...
class TechnicMoveHub(LWP3Device):
"""LEGO® Technic Move Hub (set 42176, 42214, 42239).
def name(self, *args):
"""name(name)
name() -> str
This newer hub is found in the latest Technic Control+ sets. It requires
a special password to update the firmware, so Pybricks cannot be installed
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:
name (str): New Bluetooth name of the remote. If no name is given,
this method returns the current name.
name (str): Bluetooth name of the hub. If no name is given,
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:
"""disconnect()
def drive(self, speed: int, steering: int) -> MaybeAwaitable:
"""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.
"""
@@ -457,6 +658,7 @@ if TYPE_CHECKING:
del Button
del Color
del Direction
del LWP3Device
del MaybeAwaitable
del MaybeAwaitableBool
del MaybeAwaitableFloat
+115 -18
View File
@@ -5,7 +5,7 @@
from __future__ import annotations
from typing import Tuple, Optional, overload, TYPE_CHECKING
from typing import Tuple, Union, Optional, overload, TYPE_CHECKING
from . import _common
from .parameters import Stop
@@ -92,6 +92,12 @@ class DriveBase:
Stops the robot by passively braking the motors.
"""
def hold(self) -> None:
"""hold()
Stops the robot and actively holds it in place.
"""
def distance(self) -> int:
"""distance() -> int: mm
@@ -101,11 +107,15 @@ class DriveBase:
Driven distance since last reset.
"""
def angle(self) -> int:
"""angle() -> int: deg
def angle(self) -> float:
"""angle() -> float: deg
Gets the estimated rotation angle of the drive base.
When the gyro is used for this drive base, this gives the gyro angle.
Otherwise, it gives the estimated angle estimated from the motor
displacement.
Returns:
Accumulated angle since last reset.
"""
@@ -115,31 +125,47 @@ class DriveBase:
Gets the state of the robot.
As with the :meth:`.angle` methods, the reported angle and turn rate
are those of the gyro if the gyro is used. Otherwise they are
estimated from the motor displacement.
Returns:
Tuple of distance, drive speed, angle, and turn rate of the robot.
"""
def reset(self) -> None:
"""reset()
def reset(self, distance: Number = 0, angle: Number = 0) -> None:
"""reset(distance=0, angle=0)
Resets the estimated driven distance and angle to 0."""
Resets the estimated driven distance and heading angle.
This also calls :meth:`.stop` to stop ongoing movements.
If your robot is controlled with :meth:`.use_gyro` set to ``True``,
calling this method will `also` set the gyro to the given angle.
Arguments:
distance (Number, mm): New value of the driven distance.
angle (Number, deg): New heading angle of the robot.
"""
@overload
def settings(
self,
straight_speed: Optional[Number] = None,
straight_acceleration: Optional[Number] = None,
straight_acceleration: Optional[Union[Number, Tuple[Number, Number]]] = None,
turn_rate: Optional[Number] = None,
turn_acceleration: Optional[Number] = None,
turn_acceleration: Optional[Union[Number, Tuple[Number, Number]]] = None,
) -> None: ...
@overload
def settings(self) -> Tuple[int, int, int, int]: ...
def settings(
self,
) -> Tuple[int, Union[int, Tuple[int, int]], int, Union[int, Tuple[int, int]]]: ...
def settings(self, *args):
"""
settings(straight_speed, straight_acceleration, turn_rate, turn_acceleration)
settings() -> Tuple[int, int, int, int]
settings() -> Tuple[int, Tuple[int, int], int, Tuple[int, int]]
Configures the drive base speed and acceleration.
@@ -152,15 +178,22 @@ class DriveBase:
The speed values given here do not apply to the :meth:`.drive` method,
since you provide your own speed values as arguments in that method.
Speed and rate values are treated as absolute; negative values are
converted to positive automatically.
Arguments:
straight_speed (Number, mm/s): Straight-line speed of the robot.
straight_acceleration (Number, mm/): Straight-line
acceleration and deceleration of the robot. Provide a tuple with
two values to set acceleration and deceleration separately.
straight_acceleration (Number or Tuple[Number, Number], mm/):
Straight-line acceleration and deceleration of the robot.
Provide a single value to use the same acceleration and
deceleration. Provide a tuple with two values to set them
separately.
turn_rate (Number, deg/s): Turn rate of the robot.
turn_acceleration (Number, deg/): Angular acceleration and
deceleration of the robot. Provide a tuple with
two values to set acceleration and deceleration separately.
turn_acceleration (Number or Tuple[Number, Number], deg/):
Angular acceleration and deceleration of the robot.
Provide a single value to use the same acceleration and
deceleration. Provide a tuple with two values to set them
separately.
"""
def straight(
@@ -178,9 +211,13 @@ class DriveBase:
"""
def turn(
self, angle: Number, then: Stop = Stop.HOLD, wait: bool = True
self,
angle: Number,
then: Stop = Stop.HOLD,
wait: bool = True,
absolute: bool = False,
) -> MaybeAwaitable:
"""turn(angle, then=Stop.HOLD, wait=True)
"""turn(angle, then=Stop.HOLD, wait=True, absolute=False)
Turns in place by a given angle and then stops.
@@ -189,6 +226,43 @@ class DriveBase:
then (Stop): What to do after coming to a standstill.
wait (bool): Wait for the maneuver to complete before continuing
with the rest of the program.
absolute (bool): If ``False`` (default), the robot turns _by_ the
given angle relative to its current heading. If ``True``,
the robot turns to the given absolute heading angle.
"""
def arc(
self,
radius: Number,
angle: Number = None,
distance: Number = None,
then: Stop = Stop.HOLD,
wait: bool = True,
) -> MaybeAwaitable:
"""arc(radius, angle=None, distance=None, then=Stop.HOLD, wait=True)
Drives an arc (a partial circle) with a given radius. You can specify
how far to drive using either an angle or a distance.
With a positive radius, the robot drives along a circle to its right.
With a negative radius, the robot drives along a circle to its left.
You can specify how far to travel along that circle as an angle
(degrees) or distance (mm). A positive value means driving forward
along the circle. Negative means driving in reverse.
Arguments:
radius (Number, mm): Radius of the circle.
angle (Number, deg): Angle to drive along the circle.
distance (Number, mm): Distance to drive along the circle,
measured at the center of the robot.
then (Stop): What to do after coming to a standstill.
wait (bool): Wait for the maneuver to complete before continuing
with the rest of the program.
Raises:
ValueError:
You must specify ``angle`` or ``distance``, but not both. The
radius cannot be zero. Use :meth:`.turn` for in-place turns.
"""
def curve(
@@ -224,7 +298,27 @@ class DriveBase:
with the maximum actuation signal.
Returns:
``True`` if the drivebase is stalled, ``False`` if not.
``True`` if the drive base is stalled, ``False`` if not.
"""
def move_by(self, dx: Number, dy: Number, then: Stop = Stop.HOLD) -> MaybeAwaitable:
"""move_by(dx, dy, then=Stop.HOLD)
Moves the robot by an amount given as X-and-Y coordinates on the robot
drive area. The X-axis is what was forward when the program started.
The Y-axis is 90° left of that. You can reset this by resetting the heading.
The robot first turns to the required heading and then drives the
straight-line distance. Because the heading target is absolute, the
result is independent of the robot's current heading.
Arguments:
dx (Number, mm): X-distance on the drive area.
dy (Number, mm): Y-distance on the drive area.
then (Stop): What to do after coming to a standstill.
Raises:
ValueError: If one of the distances is more than 30 m.
"""
def use_gyro(self, use_gyro: bool) -> None:
@@ -234,6 +328,9 @@ class DriveBase:
straight. Choose ``False`` to rely only on the motor's built-in
rotation sensors.
This method will automatically call :meth:`.stop` to stop ongoing
movements.
Arguments:
use_gyro (bool): ``True`` to enable, ``False`` to disable.
"""