URCap Button to run URScript

Hi,

I am new in URCap Development and I have a URCap implemented with Swing that generates a USscript when running the program, but I also want to run another two URScript to change a digital output when pushing two buttons in the Program Tab.

The code snippet of the ProgramNodeView is the following:

Where the actionperformed event of each button should call a function to generate script in the ProgramContributionNode like this (in this case they are only showing in the View some labels with random numbers)

image
image

So I want to know what should I change in both ViewNode and ContributionNode functions to reach this objective.

Thank you in advanced.

Check out this link, and add these class files to your project. They give you functions for sending lines of script for execution from java. Once you have those, something like the following code will, in this case, set digital output 1 to True:

				final ScriptCommand script = new ScriptCommand();
				//create a new String to hold the command
				String string = "set_digital_out(1,True)";
				//assign the newly created command as Primary. Secondary commands cannot consume robot time
				script.setAsPrimaryProgram();
				//add the created string to the command
				script.appendLine(string);
				//create a new instance of a ScriptSender
				final ScriptSender sender = new ScriptSender();
				//send the created script using the newly created sender
				sender.sendScriptCommand(script);

You could replace .setAsPrimaryProgram() with .setAsSecondaryProgram() if you don’t want your main program to be interrupted.

Now, that’s fine for sending script commands. But I’ll point out, it’s kinda laggy, and if you spam those buttons, you can really lag the robot. If all you’re trying to do is set a physical output via Java, that’s possible to do directly and much quicker.

import java.util.Collection;
import java.util.Iterator;

import com.ur.urcap.api.domain.io.DigitalIO;
import com.ur.urcap.api.domain.io.IO;
import com.ur.urcap.api.domain.io.IOModel;
import com.ur.urcap.api.domain.io.ModbusIO;

public class IOHelper {

	private final IOModel ioModel;

	public IOHelper(final IOModel ioModel) {
		this.ioModel = ioModel;
	}

	public DigitalIO[] getDigitalInputs() {
		final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
		ioCollection.removeIf(n -> !n.isInput());
		final int inputSize = ioCollection.size();
		final Iterator<DigitalIO> itr = ioCollection.iterator();
		final DigitalIO[] inputList = new DigitalIO[inputSize];

		for (int i = 0; i < inputSize; i++) {
			inputList[i] = itr.next();
		}
		return inputList;
	}
	
	
	
	public DigitalIO[] getDigitalOutputs() {
		final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
		ioCollection.removeIf(DigitalIO::isInput);
		final int outputSize = ioCollection.size();
		final Iterator<DigitalIO> itr = ioCollection.iterator();
		final DigitalIO[] outputList = new DigitalIO[outputSize];

		for (int i = 0; i < outputSize; i++) {
			outputList[i] = itr.next();
		}
		return outputList;
	}

	public ModbusIO[] getModBusInputs() {
		final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
		ioCollection.removeIf(n -> !n.isInput());
		final int inputSize = ioCollection.size();
		final Iterator<ModbusIO> itr = ioCollection.iterator();
		final ModbusIO[] inputList = new ModbusIO[inputSize];

		for (int i = 0; i < inputSize; i++) {
			inputList[i] = itr.next();
		}
		return inputList;
	}

	public ModbusIO[] getModBusOutputs() {
		final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
		ioCollection.removeIf(ModbusIO::isInput);
		final int outputSize = ioCollection.size();
		final Iterator<ModbusIO> itr = ioCollection.iterator();
		final ModbusIO[] outputList = new ModbusIO[outputSize];

		for (int i = 0; i < outputSize; i++) {
			outputList[i] = itr.next();
		}
		return outputList;
	}

	public DigitalIO getSpecificDigitalIO(final String defaultName) {
		final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
		final int ioCount = ioCollection.size();

		if (ioCount > 0) {
			final Iterator<DigitalIO> ioItr = ioCollection.iterator();
			while (ioItr.hasNext()) {
				final DigitalIO thisIO = ioItr.next();
				final String thisDefaultName = thisIO.getDefaultName();
				if (thisDefaultName.equals(defaultName)) {
					return thisIO;
				}
			}
		}
		return null;
	}
	
	public IO getSpecificGPIO(final String defaultName) {
		final Collection<IO> ioCollection = ioModel.getIOs();
		final int ioCount = ioCollection.size();

		if (ioCount > 0) {
			final Iterator<IO> ioItr = ioCollection.iterator();
			while (ioItr.hasNext()) {
				final IO thisIO = ioItr.next();
				final String thisDefaultName = thisIO.getDefaultName();
				if (thisDefaultName.equals(defaultName)) {
					return thisIO;
				}
			}
		}
		return null;
	}
	
	

	public ModbusIO getSpecificModBusIO(final String signalName) {
		final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
		final int ioCount = ioCollection.size();
		if (ioCount > 0) {
			final Iterator<ModbusIO> ioItr = ioCollection.iterator();
			while (ioItr.hasNext()) {
				final ModbusIO thisIO = ioItr.next();
				final String thisSignalAddress = thisIO.getName();
				if (thisSignalAddress.equals(signalName)) {
					return thisIO;
				}
			}
		}
		return null;
	}

}

Here’s the whole classfile for IOHelper, which just makes it a little easier to access the IO you want to control.
I reference this link when I need to know the name of an IO: How to obtain a list of ALL the IOs on the robot using the URCap Java API - #3 by fujikit

Once you have that, you can just say something like:

DigitalIO digitalOut1= IOHelper.getSpecificDigitalIO("digital_out[1]");

Now in the action of your button, you can do:

digitalOut1.setValue(true);

to turn it on, and setValue(false) to turn it off.

Hope some of that is helpful.

1 Like

Thanks Eric,

The first way worked for me but it is true that spamming the button produces lag in the robot. However, the second way when I add IOHelper to my project and say DigitalIO digitalOut1= IOHelper.getSpecificDigitalIO(“digital_out[1]”); it returns to me the following error tip:

Cannot make a static reference to the non-static method getSpecificDigitalIO(String) from the type IOHelper

And it suggest me to change the getSpecificDigitalIO method to static and it doesn’t work either.

Do you know which could be the problem?

Thanks for your help.

Ahh oops. I steered you wrong a little bit there. In case you see this type of error later, it is because you are making a reference to the actual class itself, instead of an instance of the class. IE by typing IOHelper.blahBlahBlah you’re trying to statically access a class that is not static.

To fix this, create an instance of IOHelper at the top of your contribution/view/whatever and access that instead.

private final IOHelper ioHelper; //Instance declaration
ioHelper = new IOHelper(context.getAPIProvider().getApplicationAPI().getIOModel()); //initialization

In this example, I use this from the toolbar, which is why I use the context as opposed to the apiProvider directly. You’ll want to use whatever can get you the getIOModel() method.

Thanks Eric again,

this time the second way worked for me and I can now set the digital outputs without lagging the robot.

I am very grateful for your help, thank you very much!