-
Notifications
You must be signed in to change notification settings - Fork 9
All components take a single port #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
907d8f7
fb5642c
cfdf242
529b601
b799da8
2445705
dd91671
6c8cd86
9eda6cc
a40bc55
6d0a38b
8c35186
86e148f
25d14ee
30e08e7
d8d2533
605e441
02e9454
cd01138
555ce33
65f1563
c3e2d21
a6b695a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,8 @@ | |
| # @author [email protected] (Alan Smith) | ||
|
|
||
| from typing import Protocol, Self | ||
| from component import Component, PortType, InvalidPortException | ||
| from component import Component, InvalidPortException | ||
| from port import Port, PortType | ||
|
|
||
| class DistanceCallable(Protocol): | ||
| def __call__(self, distance : float) -> None: | ||
|
|
@@ -30,11 +31,8 @@ def __call__(self, hue : int, saturation : int, value : int) -> None: | |
|
|
||
|
|
||
| class ColorRangeSensor(Component): | ||
| def __init__(self, ports : list[tuple[PortType, int]]): | ||
| portType, port = ports[0] | ||
| if portType != PortType.I2C_PORT: | ||
| raise InvalidPortException | ||
| self.port = port | ||
| def __init__(self, port : Port): | ||
| super().__init__( port, expectedType = PortType.I2C_PORT) | ||
|
|
||
| def get_manufacturer(self) -> str: | ||
| return "REV Robotics" | ||
|
|
@@ -54,17 +52,9 @@ def get_version(self) -> tuple[int, int, int]: | |
| def reset(self) -> None: | ||
| pass | ||
|
|
||
| def get_connection_port_type(self) -> list[PortType]: | ||
| return [PortType.I2C_PORT] | ||
|
|
||
| def periodic(self) -> None: | ||
| pass | ||
|
|
||
| # Alternative constructor to create an instance from an i2c port | ||
| @classmethod | ||
| def from_i2c_port(cls: type[Self], i2c_port: int) -> Self: | ||
| return cls([(PortType.I2C_PORT, i2c_port)]) | ||
|
|
||
|
|
||
| # Component specific methods | ||
|
|
||
| def get_color_rgb(self) -> tuple[int, int, int]: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,32 +17,26 @@ | |
| # @author [email protected] (Alan Smith) | ||
|
|
||
| from abc import ABC, abstractmethod | ||
| from enum import Enum | ||
| from typing import Protocol | ||
| from port import Port, PortType | ||
|
|
||
| class EmptyCallable(Protocol): | ||
| def __call__(self) -> None: | ||
| pass | ||
|
|
||
|
|
||
| class PortType(Enum): | ||
| CAN_PORT = 1 | ||
| SMART_IO_PORT = 2 | ||
| SMART_MOTOR_PORT = 3 | ||
| SERVO_PORT = 4 | ||
| I2C_PORT = 5 | ||
| USB_PORT = 6 | ||
|
|
||
|
|
||
| class InvalidPortException(Exception): | ||
| pass | ||
|
|
||
|
|
||
| # This is an abstract class | ||
| class Component(ABC): | ||
| @abstractmethod | ||
| def __init__(self, ports : list[tuple[PortType, int]]): | ||
| pass | ||
| def __init__(self, port : Port, expectedType : PortType): | ||
| """This has the port it is attached to, and the expected type of the port""" | ||
| if port.get_type() != expectedType: | ||
| raise InvalidPortException | ||
|
|
||
| self.port = port | ||
|
|
||
| # Returns the manufacturer of the component | ||
| @abstractmethod | ||
|
|
@@ -87,11 +81,11 @@ def stop(self) -> None: | |
| def reset(self) -> None: | ||
| pass | ||
|
|
||
| # Returns a list (can be empty, one, or multiple) of the ports this connects to | ||
| # of the PortType enumeration | ||
| @abstractmethod | ||
| def get_connection_port_type(self) -> list[PortType]: | ||
| pass | ||
| # Returns the port this connects to of the PortType enumeration | ||
| def get_connection_port_type(self) -> PortType | None: | ||
| if self.port: | ||
| return self.port.get_type() | ||
| return None | ||
|
|
||
| # This is called periodically when an opmode is running. The component might use this | ||
| # to talk to hardware and then call callbacks | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,21 +21,15 @@ | |
| __author__ = "[email protected] (Liz Looney)" | ||
|
|
||
| from typing import Self | ||
| from component import Component, PortType, InvalidPortException | ||
| from component import Component, InvalidPortException | ||
| from port import Port, PortType | ||
| import expansion_hub | ||
| import wpimath | ||
|
|
||
| # TODO(lizlooney): Update port types. | ||
|
|
||
| class ExpansionHubMotor(Component): | ||
| def __init__(self, ports : list[tuple[PortType, int]]): | ||
| port_type, hub_number = ports[0] | ||
| if port_type != PortType.USB_PORT: | ||
| raise InvalidPortException | ||
| port_type, motor_number = ports[1] | ||
| if port_type != PortType.USB_PORT: | ||
| raise InvalidPortException | ||
| self.expansion_hub_motor = expansion_hub.ExpansionHubMotor(hub_number, motor_number) | ||
| def __init__(self, port : Port): | ||
| super().__init__(port, PortType.EXPANSION_HUB_MOTOR) | ||
| self.expansion_hub_motor = expansion_hub.ExpansionHubMotor(self.port.port1.location, self.port.port2.location) | ||
|
|
||
| def get_manufacturer(self) -> str: | ||
| return "REV Robotics" | ||
|
|
@@ -62,17 +56,9 @@ def stop(self) -> None: | |
| def reset(self) -> None: | ||
| pass | ||
|
|
||
| def get_connection_port_type(self) -> list[PortType]: | ||
| return [PortType.USB_PORT, PortType.USB_PORT] | ||
|
|
||
| def periodic(self) -> None: | ||
| pass | ||
|
|
||
| # Alternative constructor to create an instance from a hub number and a motor port. | ||
| @classmethod | ||
| def from_hub_number_and_motor_number(cls: type[Self], hub_number: int, motor_number: int) -> Self: | ||
| return cls([(PortType.USB_PORT, hub_number), (PortType.USB_PORT, motor_number)]) | ||
|
|
||
| # Component specific methods | ||
|
|
||
| # Methods from expansion_hub.ExpansionHubMotor | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # @license | ||
| # Copyright 2025 Porpoiseful LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # @fileoverview This is a class to handle port types | ||
| # @author [email protected] (Alan Smith) | ||
| from abc import ABC, abstractmethod | ||
| from enum import Enum | ||
| from typing import Self | ||
|
|
||
| class PortType(Enum): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a class comment that shows examples of how to use PortType?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am happy to write a comment here, but I couldn't come up with anything about how to use it that didn't seem like "this is the type of port". Suggestions? |
||
| CAN_PORT = 1 | ||
| SMART_IO_PORT = 2 | ||
| SMART_MOTOR_PORT = 3 | ||
| SERVO_PORT = 4 | ||
| I2C_PORT = 5 | ||
| USB_PORT = 6 | ||
| EXPANSION_HUB_MOTOR_PORT = 7 # This is the port on the expansion hub | ||
| EXPANSION_HUB_SERVO_PORT = 8 # This is the port on the expansion hub | ||
|
|
||
| BASE_COMPOUND = 256 | ||
| USB_HUB = BASE_COMPOUND + 1 | ||
| EXPANSION_HUB_MOTOR = BASE_COMPOUND + 2 # This is combination expansion hub and motor | ||
| EXPANSION_HUB_SERVO = BASE_COMPOUND + 3 # This is combination expansion hub and servo | ||
|
|
||
| class Port(ABC): | ||
| """Abstract base class for all port types.""" | ||
|
|
||
| def __init__(self, port_type: PortType): | ||
| self.type = port_type | ||
|
|
||
| @abstractmethod | ||
| def get_all_ports(self) -> list[tuple[PortType, int]]: | ||
| """Return a list of all simple ports contained in this port.""" | ||
| pass | ||
|
|
||
| def get_type(self) -> PortType: | ||
| """Returns the port type""" | ||
| return self.type | ||
|
|
||
| class SimplePort(Port): | ||
| def __init__(self, port_type: PortType, location: int): | ||
| """ | ||
| Create a simple port with a type and location. | ||
|
|
||
| Args: | ||
| port_type: PortType for this port (must be a simple type) | ||
| location: int location for this port | ||
| """ | ||
| if port_type.value >= PortType.BASE_COMPOUND.value: | ||
| raise ValueError("Port must be of a simple type") | ||
| super().__init__(port_type) | ||
| self.location = location | ||
|
|
||
| def get_all_ports(self) -> list[tuple[PortType, int]]: | ||
| """Return a list containing this simple port.""" | ||
| return [(self.type, self.location)] | ||
|
|
||
| def __str__(self) -> str: | ||
| return f"SimplePort({self.type}, {self.location})" | ||
|
|
||
| class CompoundPort(Port): | ||
| def __init__(self, port_type: PortType, port1: Port, port2: Port): | ||
| """ | ||
| Create a compound port from two other ports. | ||
|
|
||
| Args: | ||
| port_type: PortType for this port (must be a compound type) | ||
| port1: First Port for compound ports | ||
| port2: Second Port for compound ports | ||
| """ | ||
| if port_type.value < PortType.BASE_COMPOUND.value: | ||
| raise ValueError("Port must be of a compound type") | ||
| super().__init__(port_type) | ||
| self.port1 = port1 | ||
| self.port2 = port2 | ||
|
|
||
| def get_all_ports(self) -> list[tuple[PortType, int]]: | ||
| """Return a list of all simple ports contained in this compound port.""" | ||
| return self.port1.get_all_ports() + self.port2.get_all_ports() | ||
|
|
||
| def __str__(self) -> str: | ||
| return f"CompoundPort({self.type}: {self.port1}, {self.port2})" | ||
Uh oh!
There was an error while loading. Please reload this page.