From 7104ff92da04f79c0fbc5b0cee072abcc7b4161e Mon Sep 17 00:00:00 2001 From: "Tianhao (Terry) Fu" Date: Thu, 12 Dec 2024 11:50:06 -0500 Subject: [PATCH] Add Button Devices (#454) --- leads_gpio/__init__.py | 1 + leads_gpio/button.py | 45 ++++++++++++++++++++++++++++++++++++++++++ leads_vec/devices.py | 31 +++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 leads_gpio/button.py diff --git a/leads_gpio/__init__.py b/leads_gpio/__init__.py index c977b6a..133c5e4 100644 --- a/leads_gpio/__init__.py +++ b/leads_gpio/__init__.py @@ -7,6 +7,7 @@ if not _find_spec("serial"): raise ImportError("Please install `pyserial` to run this module\n>>>pip install pyserial") +from leads_gpio.button import * from leads_gpio.cpu_monitor import * from leads_gpio.gps_receiver import * from leads_gpio.led import * diff --git a/leads_gpio/button.py b/leads_gpio/button.py new file mode 100644 index 0000000..083f569 --- /dev/null +++ b/leads_gpio/button.py @@ -0,0 +1,45 @@ +from typing import override as _override + +from gpiozero import Button as _Button + +from leads import Device as _Device, CallbackChain as _CallbackChain + + +class ButtonCallback(_CallbackChain): + def on_pressed(self) -> None: ... + + def on_released(self) -> None: ... + + +class Button(_Device): + """ + Listen to a button. + Supports: + - Any binary button + """ + + def __init__(self, pin: int, callback: ButtonCallback = ButtonCallback()) -> None: + super().__init__(pin) + self._button: _Button = _Button(pin) + self._callback: ButtonCallback = callback + + def _when_activated(self) -> None: + self._callback.on_pressed() + + def _when_deactivated(self) -> None: + self._callback.on_released() + + @_override + def initialize(self, *parent_tags: str) -> None: + super().initialize(*parent_tags) + self._button.when_activated = self._when_activated + self._button.when_deactivated = self._when_deactivated + + @_override + def read(self) -> bool: + return self._button.is_active + + @_override + def write(self, callback: ButtonCallback) -> None: + callback.bind_chain(self._callback) + self._callback = callback diff --git a/leads_vec/devices.py b/leads_vec/devices.py index c55129a..52f7588 100644 --- a/leads_vec/devices.py +++ b/leads_vec/devices.py @@ -4,10 +4,11 @@ Controller, CENTER_REAR_WHEEL_SPEED_SENSOR, require_config, mark_device, ODOMETER, GPS_RECEIVER, \ ConcurrentOdometer, LEFT_INDICATOR, RIGHT_INDICATOR, VOLTAGE_SENSOR, DataContainer, has_device, \ FRONT_VIEW_CAMERA, LEFT_VIEW_CAMERA, RIGHT_VIEW_CAMERA, REAR_VIEW_CAMERA, VisualDataContainer, BRAKE_INDICATOR, \ - SFT, read_device_marker, has_controller, POWER_CONTROLLER, WHEEL_SPEED_CONTROLLER, ACCELEROMETER + SFT, read_device_marker, has_controller, POWER_CONTROLLER, WHEEL_SPEED_CONTROLLER, ACCELEROMETER, require_context from leads_arduino import ArduinoMicro, WheelSpeedSensor, VoltageSensor, Accelerometer, Acceleration from leads_comm_serial import SOBD -from leads_gpio import NMEAGPSReceiver, LEDGroup, LED, LEDGroupCommand, LEDCommand, Entire, Transition, CPUMonitor +from leads_gpio import NMEAGPSReceiver, LEDGroup, LED, LEDGroupCommand, LEDCommand, Entire, Transition, Button, \ + ButtonCallback, CPUMonitor from leads_vec.config import Config from leads_video import Base64Camera, get_camera @@ -218,4 +219,30 @@ def write(self, payload: bool) -> None: ) if payload else LEDGroupCommand(LEDCommand.OFF, Entire())) +@device("lib", MAIN_CONTROLLER) +class LeftIndicatorButton(Button, ButtonCallback): + @override + def on_pressed(self) -> None: + ctx = require_context() + ctx.left_indicator(not ctx.left_indicator()) + + @override + def initialize(self, *parent_tags: str) -> None: + super().initialize(*parent_tags) + self.write(self) + + +@device("rib", MAIN_CONTROLLER) +class RightIndicatorButton(Button, ButtonCallback): + @override + def on_pressed(self) -> None: + ctx = require_context() + ctx.right_indicator(not ctx.right_indicator()) + + @override + def initialize(self, *parent_tags: str) -> None: + super().initialize(*parent_tags) + self.write(self) + + _: None = None