Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 7 additions & 1 deletion external_samples/color_range_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# @author [email protected] (Alan Smith)

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

class DistanceCallable(Protocol):
def __call__(self, distance : float) -> None:
Expand Down Expand Up @@ -52,7 +52,13 @@ def get_connection_port_type(self) -> list[PortType]:
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]:
'''gets the color in rgb (red, green, blue)'''
pass
Expand Down
11 changes: 10 additions & 1 deletion external_samples/rev_touch_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# @fileoverview This is a sample for a touch sensor
# @author [email protected] (Alan Smith)

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

class RevTouchSensor(Component):
Expand Down Expand Up @@ -51,6 +52,14 @@ def periodic(self) -> None:
self.pressed_callback()
elif old and self.released_callback:
self.released_callback()

# Alternative constructor to create an instance from a smart io port
@classmethod
def from_io_port(cls: type[Self], io_port: int) -> Self:
return cls([(PortType.SMART_IO_PORT, io_port)])

# Component specific methods

def _read_hardware(self):
# here read hardware to get the current value of the sensor and set self.is_pressed
pass
Expand All @@ -67,4 +76,4 @@ def register_when_pressed(self, callback: EmptyCallable) -> None:

def register_when_released(self, callback: EmptyCallable) -> None:
'''Event when touch sensor is released (after being pressed)'''
self.released_callback = callback
self.released_callback = callback
10 changes: 7 additions & 3 deletions external_samples/servo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# @fileoverview This is a sample for a servo
# @author [email protected] (Alan Smith)

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

class Servo(Component):
Expand Down Expand Up @@ -44,14 +45,17 @@ def get_connection_port_type(self) -> list[PortType]:
def periodic(self) -> None:
pass

# Alternative constructor to create an instance from an servo port
@classmethod
def from_servo_port(cls: type[Self], servo_port: int) -> Self:
return cls([(PortType.SERVO_PORT, servo_port)])

# Component specific methods

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)



11 changes: 9 additions & 2 deletions external_samples/smart_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@

# @fileoverview This is a sample for a smart motor
# @author [email protected] (Alan Smith)

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

class SmartMotor(Component):
class SmartMotor(Component):
def __init__(self, ports : list[tuple[PortType, int]]):
portType, port = ports[0]
if portType != PortType.SMART_MOTOR_PORT:
Expand All @@ -43,7 +45,13 @@ def get_connection_port_type(self) -> list[PortType]:
def periodic(self) -> None:
pass

# Alternative constructor to create an instance from a motor port
@classmethod
def from_motor_port(cls: type[Self], motor_port: int) -> Self:
return cls([(PortType.SMART_MOTOR_PORT, motor_port)])

# Component specific methods

def set_speed(self, speed: float) -> None:
'''Set the motor to a speed between -1 and 1'''
# TODO: send to the hardware the speed of the motor
Expand All @@ -64,4 +72,3 @@ def get_angle_degrees(self) -> float:
def reset_relative_encoder(self) -> None:
'''Reset the relative encoder value to 0'''
pass

8 changes: 6 additions & 2 deletions external_samples/spark_mini.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

__author__ = "[email protected] (Liz Looney)"

from typing import Self
from component import Component, PortType, InvalidPortException
import wpilib
import wpimath
Expand All @@ -32,8 +33,6 @@ def __init__(self, ports : list[tuple[PortType, int]]):
raise InvalidPortException
self.spark_mini = wpilib.SparkMini(port)

# Component methods

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

Expand Down Expand Up @@ -62,6 +61,11 @@ def get_connection_port_type(self) -> list[PortType]:
def periodic(self) -> None:
pass

# Alternative constructor to create an instance from a motor port
@classmethod
def from_motor_port(cls: type[Self], motor_port: int) -> Self:
return cls([(PortType.SMART_MOTOR_PORT, motor_port)])

# Component specific methods

# Methods from wpilib.PWMMotorController
Expand Down
8 changes: 6 additions & 2 deletions external_samples/sparkfun_led_stick.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

__author__ = "[email protected] (Liz Looney)"

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

Expand All @@ -24,8 +25,6 @@ def __init__(self, ports : list[tuple[PortType, int]]):
raise InvalidPortException
self.port = port

# Component methods

def get_manufacturer(self) -> str:
return "SparkFun"

Expand Down Expand Up @@ -53,6 +52,11 @@ def get_connection_port_type(self) -> list[PortType]:
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)])

# SparkFunLEDStick methods

def set_color(self, position: int, color: wpilib.Color) -> None:
Expand Down
72 changes: 37 additions & 35 deletions src/blocks/mrc_call_python_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import { Order } from 'blockly/python';
import { ClassMethodDefExtraState } from './mrc_class_method_def'
import { getClassData, getAllowedTypesForSetCheck, getOutputCheck } from './utils/python';
import { FunctionData, findSuperFunctionData } from './utils/python_json_types';
import * as value from './utils/value';
import * as variable from './utils/variable';
import * as Value from './utils/value';
import * as Variable from './utils/variable';
import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
import { createFieldDropdown } from '../fields/FieldDropdown';
import { createFieldNonEditableText } from '../fields/FieldNonEditableText';
import { MRC_STYLE_FUNCTIONS } from '../themes/styles'
import * as toolboxItems from '../toolbox/items';
import * as commonStorage from '../storage/common_storage';
import * as ToolboxItems from '../toolbox/items';
import * as CommonStorage from '../storage/common_storage';


// A block to call a python function.
Expand Down Expand Up @@ -66,7 +66,7 @@ export type FunctionArg = {
export function addModuleFunctionBlocks(
moduleName: string,
functions: FunctionData[],
contents: toolboxItems.ContentsType[]) {
contents: ToolboxItems.ContentsType[]) {
for (const functionData of functions) {
const block = createModuleFunctionOrStaticMethodBlock(
FunctionKind.MODULE, moduleName, moduleName, functionData);
Expand All @@ -77,7 +77,7 @@ export function addModuleFunctionBlocks(
export function addStaticMethodBlocks(
importModule: string,
functions: FunctionData[],
contents: toolboxItems.ContentsType[]) {
contents: ToolboxItems.ContentsType[]) {
for (const functionData of functions) {
if (functionData.declaringClassName) {
const block = createModuleFunctionOrStaticMethodBlock(
Expand All @@ -91,7 +91,7 @@ function createModuleFunctionOrStaticMethodBlock(
functionKind: FunctionKind,
importModule: string,
moduleOrClassName: string,
functionData: FunctionData): toolboxItems.Block {
functionData: FunctionData): ToolboxItems.Block {
const extraState: CallPythonFunctionExtraState = {
functionKind: functionKind,
returnType: functionData.returnType,
Expand All @@ -110,16 +110,16 @@ function createModuleFunctionOrStaticMethodBlock(
'type': argData.type,
});
// Check if we should plug a variable getter block into the argument input socket.
const input = value.valueForFunctionArgInput(argData.type, argData.defaultValue);
const input = Value.valueForFunctionArgInput(argData.type, argData.defaultValue);
if (input) {
inputs['ARG' + i] = input;
}
}
let block = new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
let block = new ToolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
if (functionData.returnType && functionData.returnType != 'None') {
const varName = variable.varNameForType(functionData.returnType);
const varName = Variable.varNameForType(functionData.returnType);
if (varName) {
block = variable.createVariableSetterBlock(varName, block);
block = Variable.createVariableSetterBlock(varName, block);
}
}
return block;
Expand All @@ -128,7 +128,7 @@ function createModuleFunctionOrStaticMethodBlock(
export function addConstructorBlocks(
importModule: string,
functions: FunctionData[],
contents: toolboxItems.ContentsType[]) {
contents: ToolboxItems.ContentsType[]) {
for (const functionData of functions) {
const block = createConstructorBlock(importModule, functionData);
contents.push(block);
Expand All @@ -137,7 +137,7 @@ export function addConstructorBlocks(

function createConstructorBlock(
importModule: string,
functionData: FunctionData): toolboxItems.Block {
functionData: FunctionData): ToolboxItems.Block {
const extraState: CallPythonFunctionExtraState = {
functionKind: FunctionKind.CONSTRUCTOR,
returnType: functionData.returnType,
Expand All @@ -155,32 +155,32 @@ function createConstructorBlock(
'type': argData.type,
});
// Check if we should plug a variable getter block into the argument input socket.
const input = value.valueForFunctionArgInput(argData.type, argData.defaultValue);
const input = Value.valueForFunctionArgInput(argData.type, argData.defaultValue);
if (input) {
inputs['ARG' + i] = input;
}
}
let block = new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
let block = new ToolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
if (functionData.returnType && functionData.returnType != 'None') {
const varName = variable.varNameForType(functionData.returnType);
const varName = Variable.varNameForType(functionData.returnType);
if (varName) {
block = variable.createVariableSetterBlock(varName, block);
block = Variable.createVariableSetterBlock(varName, block);
}
}
return block;
}

export function addInstanceMethodBlocks(
functions: FunctionData[],
contents: toolboxItems.ContentsType[]) {
contents: ToolboxItems.ContentsType[]) {
for (const functionData of functions) {
const block = createInstanceMethodBlock(functionData);
contents.push(block);
}
}

function createInstanceMethodBlock(
functionData: FunctionData): toolboxItems.Block {
functionData: FunctionData): ToolboxItems.Block {
const extraState: CallPythonFunctionExtraState = {
functionKind: FunctionKind.INSTANCE,
returnType: functionData.returnType,
Expand All @@ -195,32 +195,32 @@ function createInstanceMethodBlock(
const argData = functionData.args[i];
let argName = argData.name;
if (i === 0 && argName === 'self' && functionData.declaringClassName) {
argName = variable.getSelfArgName(functionData.declaringClassName);
argName = Variable.getSelfArgName(functionData.declaringClassName);
}
extraState.args.push({
'name': argName,
'type': argData.type,
});
// Check if we should plug a variable getter block into the argument input socket.
const input = value.valueForFunctionArgInput(argData.type, argData.defaultValue);
const input = Value.valueForFunctionArgInput(argData.type, argData.defaultValue);
if (input) {
inputs['ARG' + i] = input;
}
}
let block = new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
let block = new ToolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
if (functionData.returnType && functionData.returnType != 'None') {
const varName = variable.varNameForType(functionData.returnType);
const varName = Variable.varNameForType(functionData.returnType);
if (varName) {
block = variable.createVariableSetterBlock(varName, block);
block = Variable.createVariableSetterBlock(varName, block);
}
}
return block;
}

export function addInstanceComponentBlocks(
export function getInstanceComponentBlocks(
componentType: string,
componentName: string,
contents: toolboxItems.ContentsType[]) {
componentName: string) {
const contents: ToolboxItems.ContentsType[] = [];

const classData = getClassData(componentType);
if (!classData) {
Expand All @@ -242,10 +242,12 @@ export function addInstanceComponentBlocks(
const block = createInstanceComponentBlock(componentName, functionData);
contents.push(block);
}

return contents;
}

function createInstanceComponentBlock(
componentName: string, functionData: FunctionData): toolboxItems.Block {
componentName: string, functionData: FunctionData): ToolboxItems.Block {
const extraState: CallPythonFunctionExtraState = {
functionKind: FunctionKind.INSTANCE_COMPONENT,
returnType: functionData.returnType,
Expand All @@ -270,17 +272,17 @@ function createInstanceComponentBlock(
'type': argData.type,
});
// Check if we should plug a variable getter block into the argument input socket.
const input = value.valueForFunctionArgInput(argData.type, argData.defaultValue);
const input = Value.valueForFunctionArgInput(argData.type, argData.defaultValue);
if (input) {
// Because we skipped the self argument, use i - 1 when filling the inputs array.
inputs['ARG' + (i - 1)] = input;
}
}
let block = new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
let block = new ToolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
if (functionData.returnType && functionData.returnType != 'None') {
const varName = variable.varNameForType(functionData.returnType);
const varName = Variable.varNameForType(functionData.returnType);
if (varName) {
block = variable.createVariableSetterBlock(varName, block);
block = Variable.createVariableSetterBlock(varName, block);
}
}
return block;
Expand Down Expand Up @@ -683,11 +685,11 @@ export const pythonFromBlock = function(
: block.getFieldValue(FIELD_FUNCTION_NAME);
// Generate the correct code depending on the module type.
switch (generator.getModuleType()) {
case commonStorage.MODULE_TYPE_ROBOT:
case commonStorage.MODULE_TYPE_MECHANISM:
case CommonStorage.MODULE_TYPE_ROBOT:
case CommonStorage.MODULE_TYPE_MECHANISM:
code = 'self.';
break;
case commonStorage.MODULE_TYPE_OPMODE:
case CommonStorage.MODULE_TYPE_OPMODE:
default:
code = 'self.robot.';
break;
Expand Down
Loading