pylgbst

repository·master·Indexed 20 days ago

https://github.com/undera/pylgbst

A Python library for interacting with LEGO Move Hubs and PoweredUp Hubs via Bluetooth Low Energy (BLE). It provides functionality to control motors (speed, time, and angle), read sensors (vision, tilt, battery), and manage LED/headlight states. The library supports multiple Bluetooth backends including bleak, pygatt, gatt, gattlib, and bluepy, and includes an AdvancedButton class for complex press patterns like double-clicks and long-presses.

Tokens
6.7K
Snippets
22
Records
34
Agent score
69%

What's inside pylgbst

  1. Available Move Hub features

    master

    The library provides support for the following hardware features:

    • Motors: Constant, angled, and timed movement; rotation sensor subscription.
    • Vision Sensor: Distance, color, and luminosity measurement modes.
    • Tilt Sensor: 2-axis, 3-axis, and bump detection modes.
    • RGB LED: Color change.
    • Headlight: Brightness control.
    • Push Button: Status subscription.
    • Power: Battery voltage and current subscription.
    • Peripherals: Auto-detection of connected devices.
  2. Use the MoveHub class

    master

    The MoveHub class is a specialized extension of the GenericHub class designed specifically for the MoveHub brick. It provides pre-configured access to internal motor ports and built-in sensors. All standard Hub operations (from GenericHub) are available.

    Note on Device Detection: When you instantiate MoveHub, it waits up to 1 minute for built-in devices (motors on ports A and B, tilt sensor, LED, and battery) to appear. If you are using external sensors, it is recommended to call time.sleep() for a few seconds after instantiation to ensure all devices are detected.

    from pylgbst.hub import MoveHub
    
    hub = MoveHub()
    # It is recommended to sleep briefly to allow device detection to complete
    import time
    time.sleep(2.0)
  3. Identify supported peripheral types

    master

    The library provides dedicated classes for common peripheral devices. If a device is recognized, use its specific class to access high-level features. If the device is unknown, it will be instantiated as a generic Peripheral class, which allows for low-level interactions using standard subscription and sensor info commands.

    - Motors
    - RGB LED
    - Headlight
    - Tilt Sensor
    - Vision Sensor (color and/or distance)
    - Voltage and Current Sensors
    - Temperature
  4. Use the Generic Peripheral class for unknown devices

    master

    If a peripheral attached to the Hub is not recognized by the library, it is automatically assigned the generic Peripheral class. While you won't have access to specialized high-level methods, you can still perform low-level operations such as:

    • Subscribing to sensor data.
    • Using sensor info getting commands.
  5. Install pylgbst with a Bluetooth backend

    master

    To use pylgbst, you must install it along with a Bluetooth backend library. The recommended backend is bleak, which supports Linux, Windows, and MacOS.

    Install the library and the bleak backend using:

    pip install -U pylgbst[bleak]
  6. Subscribe to Tilt Sensor data

    master

    You can subscribe to the TiltSensor on a MoveHub instance using different modes depending on whether you need raw acceleration/angle data or simple state detection (e.g., detecting if the hub is 'UP' or 'DOWN'). Use hub.tilt_sensor.subscribe(callback, mode=...) to start receiving updates and hub.tilt_sensor.unsubscribe(callback) to stop.

    from pylgbst.hub import MoveHub, TiltSensor
    import time
    
    def callback(roll, pitch, yaw):
        print("Roll: %s / Pitch: %s / Yaw: %s" % (roll, pitch, yaw))
    
    hub = MoveHub()
    
    hub.tilt_sensor.subscribe(callback, mode=TiltSensor.MODE_3AXIS_ACCEL)
    time.sleep(60) # turn MoveHub block in different ways
    hub.tilt_sensor.unsubscribe(callback)
  7. Initialize MoveHub and detect peripherals

    master

    After installation, you can instantiate a MoveHub object. By default, it attempts to auto-detect the hub and its connected peripherals. You can iterate over the hub.peripherals attribute to access connected devices like motors or sensors.

    Each peripheral type has its own specific methods for controlling hardware or reading sensor data.

    from pylgbst.hub import MoveHub
    
    hub = MoveHub()
    
    for device in hub.peripherals:
        print(device)
  8. Execute motor operations in parallel using non-blocking calls

    master

    By default, motor methods like timed and angled are blocking (they wait for the operation to finish before moving to the next line of code). To run multiple motors simultaneously, set wait_complete=False in the method call, and then use wait_complete() on the motor objects to synchronize your code once the parallel tasks are finished.

    from pylgbst.hub import MoveHub
    
    hub = MoveHub()
    
    # Start motor A and B simultaneously without waiting for them to finish
    hub.motor_A.timed(0.5, 0.8, wait_complete=False)
    hub.motor_B.angled(90, 0.8, wait_complete=False)
    
    # Wait for both operations to complete before proceeding
    hub.motor_A.wait_complete()
    hub.motor_B.wait_complete()
  9. Subscribe to sensor data with granularity control

    master

    Sensors can be subscribed to using different 'subscription modes' which determine the callback parameters and value semantics.

    When subscribing, you can provide an optional granularity parameter (default is 1). This parameter controls the frequency of notifications from the Hub based on value changes:

    • granularity=0: The Hub sends notifications constantly.
    • granularity=5: The Hub only issues a notification when the sensor value changes by 5 or more.

    Important Notes:

    • You can subscribe multiple times to the same sensor. However, only the very last subscription mode configured will be in effect, though multiple subscriber callbacks can still receive notifications.
    • Best Practice: Always unsubscribe from all sensor subscriptions before exiting your program, particularly when using DebugServer.
  10. Configure Bluetooth backend prerequisites

    master

    The library requires a Bluetooth backend to communicate with the Move Hub via BLE. Depending on your OS and hardware, choose one of the following:

    BackendInstallation CommandSupported Platforms
    bleak (Recommended)pip install bleakLinux, Windows, MacOS
    pygattpip install pygattWindows, Linux
    gattpip install gattLinux (not Windows)
    gattlibpip install gattlibLinux (not Windows, requires sudo)
    bluepypip install bluepyLinux (including Raspbian)

    Note for Windows users:

  11. Subscribe to Vision Sensor modes

    master

    The VisionSensor can be subscribed to using different modes that determine the arguments passed to your callback function. The default mode is COLOR_DISTANCE_FLOAT, which provides both the detected color and the distance in inches.

    Detected Colors: Only specific colors can be detected: BLACK, BLUE, CYAN, YELLOW, RED, and WHITE. For best results, the sample must be very close to the sensor.

    Distance Range: Distance is measured from 0 to 10 inches, with higher precision available for the last inch.

    from pylgbst.hub import MoveHub, VisionSensor
    import time
    
    def callback(color, distance):
        print("Color: %s / Distance: %s" % (color, distance))
    
    hub = MoveHub()
    
    hub.vision_sensor.subscribe(callback, mode=VisionSensor.COLOR_DISTANCE_FLOAT)
    time.sleep(60) # play with sensor while it waits   
    hub.vision_sensor.unsubscribe(callback)
  12. Ensure clean Bluetooth disconnection using try...finally

    master

    To prevent issues with the Bluetooth subsystem and ensure subsequent reconnections to a MoveHub are successful, always call disconnect() on the connection object when finished. The recommended pattern is to use a try...finally block.

    Note: Do not place the get_connection_auto() call inside the try block; call it before the block starts so that the finally clause can reliably access the connection object.

    from pylgbst import get_connection_auto
    from pylgbst.hub import Hub
    
    conn = get_connection_auto()  # ! don't put this into `try` block
    try:
        hub = Hub(conn)
        # ... perform hub operations ...
    finally:
        conn.disconnect()