Skip to content

Commit

Permalink
pybricks.common: Add new BLE class.
Browse files Browse the repository at this point in the history
This adds a new BLE class that is used for connectionless broadcasting/
observing on hubs with built-in Bluetooth Low Energy.

Also see pybricks/pybricks-micropython#158.
  • Loading branch information
dlech committed May 16, 2023
1 parent b4ff3af commit 3274cef
Show file tree
Hide file tree
Showing 16 changed files with 413 additions and 12 deletions.
1 change: 1 addition & 0 deletions doc/common/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ def on_missing_reference(
# warnings when Sphinx tries to cross reference units like deg/s. For
# consistency, we also treat units without special characters this way.
for unit in [
"dBm",
"deg",
"deg/s",
"deg/s²",
Expand Down
22 changes: 22 additions & 0 deletions doc/main/hubs/cityhub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ City Hub

.. automethod:: pybricks.hubs::CityHub.light.animate

.. rubric:: Using connectionless Bluetooth messaging

``ble.broadcast()`` does not work on ``CityHub`` due to a bug in the
Bluetooth chip firmware.

.. automethod:: pybricks.hubs::CityHub.ble.observe

.. automethod:: pybricks.hubs::CityHub.ble.signal_strength

.. automethod:: pybricks.hubs::CityHub.ble.version

.. rubric:: Using the battery

.. automethod:: pybricks.hubs::CityHub.battery.voltage
Expand Down Expand Up @@ -70,6 +81,17 @@ Creating light animations
.. literalinclude::
../../../examples/pup/hub_common/build/light_animate_cityhub.py


Bluetooth examples
------------------

Observing data from other hubs
******************************

.. literalinclude::
../../../examples/pup/hub_common/build/ble_observe_cityhub.py


Button and system examples
----------------------------------

Expand Down
27 changes: 27 additions & 0 deletions doc/main/hubs/essentialhub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ Essential Hub

.. automethod:: pybricks.hubs::EssentialHub.imu.settings

.. rubric:: Using connectionless Bluetooth messaging

.. automethod:: pybricks.hubs::EssentialHub.ble.broadcast

.. automethod:: pybricks.hubs::EssentialHub.ble.observe

.. automethod:: pybricks.hubs::EssentialHub.ble.signal_strength

.. automethod:: pybricks.hubs::EssentialHub.ble.version

.. rubric:: Using the battery

.. automethod:: pybricks.hubs::EssentialHub.battery.voltage
Expand Down Expand Up @@ -136,6 +146,23 @@ 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
----------------------------------

Expand Down
27 changes: 27 additions & 0 deletions doc/main/hubs/movehub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ Move Hub

Changed acceleration units from m/s² to mm/s².

.. rubric:: Using connectionless Bluetooth messaging

.. automethod:: pybricks.hubs::MoveHub.ble.broadcast

.. automethod:: pybricks.hubs::MoveHub.ble.observe

.. automethod:: pybricks.hubs::MoveHub.ble.signal_strength

.. automethod:: pybricks.hubs::MoveHub.ble.version

.. rubric:: Using the battery

.. automethod:: pybricks.hubs::MoveHub.battery.voltage
Expand Down Expand Up @@ -85,6 +95,23 @@ 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
----------------------------------

Expand Down
27 changes: 27 additions & 0 deletions doc/main/hubs/primehub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ Prime Hub / Inventor Hub

.. automethod:: pybricks.hubs::PrimeHub.speaker.play_notes

.. rubric:: Using connectionless Bluetooth messaging

.. automethod:: pybricks.hubs::PrimeHub.ble.broadcast

.. automethod:: pybricks.hubs::PrimeHub.ble.observe

.. automethod:: pybricks.hubs::PrimeHub.ble.signal_strength

.. automethod:: pybricks.hubs::PrimeHub.ble.version

.. rubric:: Using the battery

.. automethod:: pybricks.hubs::PrimeHub.battery.voltage
Expand Down Expand Up @@ -247,6 +257,23 @@ 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
----------------------------------

Expand Down
27 changes: 27 additions & 0 deletions doc/main/hubs/technichub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ Technic Hub

.. automethod:: pybricks.hubs::TechnicHub.imu.settings

.. rubric:: Using connectionless Bluetooth messaging

.. automethod:: pybricks.hubs::TechnicHub.ble.broadcast

.. automethod:: pybricks.hubs::TechnicHub.ble.observe

.. automethod:: pybricks.hubs::TechnicHub.ble.signal_strength

.. automethod:: pybricks.hubs::TechnicHub.ble.version

.. rubric:: Using the battery

.. automethod:: pybricks.hubs::TechnicHub.battery.voltage
Expand Down Expand Up @@ -128,6 +138,23 @@ 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
----------------------------------

Expand Down
24 changes: 24 additions & 0 deletions examples/pup/hub_common/ble_broadcast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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

# Initialize the hub.
hub = ThisHub(broadcast_channel=1)

# Initialize the motors.
left_motor = Motor(Port.A)
right_motor = Motor(Port.B)

while True:
# Read the motor angles to be sent to the other hub.
left_angle = left_motor.angle()
right_angle = right_motor.angle()

# Set the broadcast data and start broadcasting if not already doing so.
hub.ble.broadcast(left_angle, right_angle)

# Broadcasts are only sent every 100 milliseconds, so there is no reason
# to call the broadcast() method more often than that.
wait(100)
39 changes: 39 additions & 0 deletions examples/pup/hub_common/ble_observe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ThisHub = MoveHub CityHub TechnicHub PrimeHub EssentialHub
from pybricks.hubs import ThisHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Color, Port
from pybricks.tools import wait

# Initialize the hub.
hub = ThisHub(observe_channels=[1])

# Initialize the motors.
left_motor = Motor(Port.A)
right_motor = Motor(Port.B)

while True:
# Receive broadcast from the other hub.

data = hub.ble.observe(1)

if data is None:
# No data has been received in the last 1 second.
hub.light.on(Color.RED)
else:
# 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
# other hub.
left_angle = data[0]
right_angle = data[1]

# Make the motors on this hub mirror the position of the
# motors on the other hub.
left_motor.track_target(left_angle)
right_motor.track_target(right_angle)

# Broadcasts are only sent every 100 milliseconds, so there is
# no reason to call the observe() method more often than that.
wait(100)
1 change: 1 addition & 0 deletions jedi/tests/test_complete_city_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"button",
"light",
"system",
Expand Down
1 change: 1 addition & 0 deletions jedi/tests/test_complete_essential_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"button",
"charger",
"imu",
Expand Down
1 change: 1 addition & 0 deletions jedi/tests/test_complete_move_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"button",
"imu",
"light",
Expand Down
1 change: 1 addition & 0 deletions jedi/tests/test_complete_prime_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ 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",
Expand Down
1 change: 1 addition & 0 deletions jedi/tests/test_complete_technic_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
"ble",
"button",
"imu",
"light",
Expand Down
42 changes: 38 additions & 4 deletions jedi/tests/test_get_signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,51 @@ def _get_constructor_signature(module: str, type: str) -> SignatureHelp:


CONSTRUCTOR_PARAMS = [
pytest.param("pybricks.hubs", "MoveHub", [[]]),
pytest.param("pybricks.hubs", "CityHub", [[]]),
pytest.param(
"pybricks.hubs",
"MoveHub",
[["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
),
pytest.param(
"pybricks.hubs",
"CityHub",
[["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
),
pytest.param(
"pybricks.hubs",
"TechnicHub",
[["top_side: Axis=Axis.Z", "front_side: Axis=Axis.X"]],
[
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
[["top_side: Axis=Axis.Z", "front_side: Axis=Axis.X"]],
[
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
pytest.param(
"pybricks.hubs",
"EssentialHub",
[
[
"top_side: Axis=Axis.Z",
"front_side: Axis=Axis.X",
"broadcast_channel: int=0",
"observe_channels: Sequence[int]=[]",
]
],
),
pytest.param(
"pybricks.pupdevices",
Expand Down

0 comments on commit 3274cef

Please sign in to comment.