Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion external_samples/color_range_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,51 @@
# @fileoverview This is a sample for a color/range sensor
# @author [email protected] (Alan Smith)

from component import Component, PortType, InvalidPortException
from typing import Protocol, Self
from component import Component, PortType, InvalidPortException

class DistanceCallable(Protocol):
def __call__(self, distance : float) -> None:
pass


class ColorCallable(Protocol):
def __call__(self, hue : int, saturation : int, value : int) -> None:
pass


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 get_manufacturer(self) -> str:
return "REV Robotics"

def get_name(self) -> str:
return "Color Sensor v3"

def get_part_number(self) -> str:
return "REV-31-1557"

def get_url(self) -> str:
return "https://www.revrobotics.com/rev-31-1557"

def get_version(self) -> tuple[int, int, int]:
return (1, 0, 0)

def stop(self) -> None:
# send stop command to sensor
pass

def reset(self) -> None:
pass

def get_connection_port_type(self) -> list[PortType]:
return [PortType.I2C_PORT]

def periodic(self) -> None:
pass

Expand All @@ -62,9 +74,11 @@ def from_i2c_port(cls: type[Self], i2c_port: int) -> Self:
def get_color_rgb(self) -> tuple[int, int, int]:
'''gets the color in rgb (red, green, blue)'''
pass

def get_color_hsv(self) -> tuple[int, int, int]:
'''gets the color in hsv (hue, saturation, value)'''
pass

def get_distance_mm(self) -> float:
'''gets the distance of the object seen'''
pass
Expand Down
37 changes: 23 additions & 14 deletions external_samples/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
class EmptyCallable(Protocol):
def __call__(self) -> None:
pass


class PortType(Enum):
CAN_PORT = 1
SMART_IO_PORT = 2
Expand All @@ -31,37 +33,44 @@ class PortType(Enum):
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
# This is the manufacturer of the component

# Returns the manufacturer of the component
@abstractmethod
def get_manufacturer(self) -> str:
pass
# This is the name of the component
def get_manufacturer(self) -> str:
pass

# Returns the name of the component
@abstractmethod
def get_name(self) -> str:
def get_name(self) -> str:
pass
# This is the part number of the component

# Returns the part number of the component
@abstractmethod
def get_part_number(self) -> str:
def get_part_number(self) -> str:
pass
# This is the URL of the component

# Returns the URL of the component
@abstractmethod
def get_url(self) -> str:
def get_url(self) -> str:
pass
# This is the version of the software (returned as a (major, minor, patch) tuple where

# Returns the version of the software (returned as a (major, minor, patch) tuple where
# major, minor and patch are all positive integers
# This MUST follow semantic versioning as described here: https://semver.org/
@abstractmethod
def get_version(self) -> tuple[int, int, int]:
def get_version(self) -> tuple[int, int, int]:
pass

# This stops all movement (if any) for the component
@abstractmethod
def stop(self) -> None:
Expand All @@ -73,13 +82,13 @@ def stop(self) -> None:
def reset(self) -> None:
pass

# This returns a list (can be empty, one, or multiple) of the ports this connects to
# 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

# This is called periodically when an opmode is running. The component might use this
# This is called periodically when an opmode is running. The component might use this
# to talk to hardware and then call callbacks
@abstractmethod
def periodic(self) -> None:
Expand Down
9 changes: 9 additions & 0 deletions external_samples/rev_touch_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,33 @@ def __init__(self, ports : list[tuple[PortType, int]]):
if portType != PortType.SMART_IO_PORT:
raise InvalidPortException
self.port = port

def get_manufacturer(self) -> str:
return "REV Robotics"

def get_name(self) -> str:
return "Touch Sensor"

def get_part_number(self) -> str:
return "REV-31-1425"

def get_url(self) -> str:
return "https://www.revrobotics.com/rev-31-1425/"

def get_version(self) -> tuple[int, int, int]:
return (1, 0, 0)

def stop(self) -> None:
pass

def reset(self) -> None:
self.pressed_callback = None
self.released_callback = None
pass

def get_connection_port_type(self) -> list[PortType]:
return [PortType.SMART_IO_PORT]

def periodic(self) -> None:
old = self.is_pressed
self._read_hardware()
Expand Down
10 changes: 10 additions & 0 deletions external_samples/servo.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,32 @@ def __init__(self, ports : list[tuple[PortType, int]]):
if portType != PortType.SERVO_PORT:
raise InvalidPortException
self.port = port

def get_manufacturer(self) -> str:
return "REV Robotics"

def get_name(self) -> str:
return "SRS Servo"

def get_part_number(self) -> str:
return "REV-41-1097"

def get_url(self) -> str:
return "https://www.revrobotics.com/rev-41-1097/"

def get_version(self) -> tuple[int, int, int]:
return (1, 0, 0)

def stop(self) -> None:
# De-energize servo port
pass

def reset(self) -> None:
pass

def get_connection_port_type(self) -> list[PortType]:
return [PortType.SERVO_PORT]

def periodic(self) -> None:
pass

Expand All @@ -56,6 +65,7 @@ def set_position(self, pos: float) -> None:
'''Set the servo to a position between 0 and 1'''
# sends to the hardware the position of the servo
pass

def set_angle_degrees(self, angle: float) -> None:
'''Set the servo to an angle between 0 and 270'''
self.set_position(angle / 270.0)
9 changes: 9 additions & 0 deletions external_samples/smart_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,32 @@ def __init__(self, ports : list[tuple[PortType, int]]):
if portType != PortType.SMART_MOTOR_PORT:
raise InvalidPortException
self.port = port

def get_manufacturer(self) -> str:
return "REV Robotics"

def get_name(self) -> str:
return "DC Motor"

def get_part_number(self) -> str:
return "REV-xx-xxxx"

def get_url(self) -> str:
return "https://www.revrobotics.com/rev-xx-xxxx"

def get_version(self) -> tuple[int, int, int]:
return (1, 0, 0)

def stop(self) -> None:
# send stop command to motor
pass

def reset(self) -> None:
pass

def get_connection_port_type(self) -> list[PortType]:
return [PortType.SMART_MOTOR_PORT]

def periodic(self) -> None:
pass

Expand Down
2 changes: 1 addition & 1 deletion external_samples/spark_mini.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import wpimath
import wpiutil

class SparkMiniComponent(Component):
class SparkMini(Component):
def __init__(self, ports : list[tuple[PortType, int]]):
portType, port = ports[0]
if portType != PortType.SMART_MOTOR_PORT:
Expand Down
25 changes: 14 additions & 11 deletions python_tools/generate_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
# Server python scripts
sys.path.append("../server_python_scripts")
import blocks_base_classes
import expansion_hub # TODO(lizlooney): update this when it is built into robotpy.

# External samples
sys.path.append("../external_samples")
Expand Down Expand Up @@ -84,6 +85,7 @@ def main(argv):
pathlib.Path(f'{FLAGS.output_directory}/generated/').mkdir(parents=True, exist_ok=True)

robotpy_modules = [
expansion_hub, # TODO(lizlooney): update this when it is built into robotpy.
ntcore,
wpilib,
wpilib.counter,
Expand All @@ -110,16 +112,9 @@ def main(argv):
wpinet,
wpiutil,
]
json_generator = json_util.JsonGenerator(robotpy_modules)
json_generator_robotpy = json_util.JsonGenerator(robotpy_modules)
file_path = f'{FLAGS.output_directory}/generated/robotpy_data.json'
json_generator.writeJsonFile(file_path)

server_python_scripts = [
blocks_base_classes,
]
json_generator = json_util.JsonGenerator(server_python_scripts)
file_path = f'{FLAGS.output_directory}/generated/server_python_scripts.json'
json_generator.writeJsonFile(file_path)
json_generator_robotpy.writeJsonFile(file_path)

external_samples_modules = [
color_range_sensor,
Expand All @@ -130,10 +125,18 @@ def main(argv):
spark_mini,
sparkfun_led_stick,
]
json_generator = json_util.JsonGenerator(external_samples_modules)
json_generator_external_samples = json_util.JsonGenerator(
external_samples_modules, [json_generator_robotpy])
file_path = f'{FLAGS.output_directory}/generated/external_samples_data.json'
json_generator.writeJsonFile(file_path)
json_generator_external_samples.writeJsonFile(file_path)

server_python_scripts = [
blocks_base_classes,
]
json_generator_server_python = json_util.JsonGenerator(
server_python_scripts, [json_generator_robotpy])
file_path = f'{FLAGS.output_directory}/generated/server_python_scripts.json'
json_generator_server_python.writeJsonFile(file_path)

if __name__ == '__main__':
app.run(main)
Loading