URCAP Limitations access feasibility

We are currently developing a URCap and have encountered some limitations regarding live input status updates on the Java (UI) side of the URCap. As per our understanding:

  • URCap has two parts:

    1. Java side → used for building the user interface

    2. Robot script side → runs during program execution

  • Live input status (e.g., Configurable Digital Inputs) is only accessible inside the robot script using:
    get_configurable_digital_in(x)

  • The Java side does not have direct access to this real-time data, which means that input ON/OFF status cannot be shown in the UI by default.

Because of this limitation, we are unable to implement the following features in our URCap screen:

  1. Cycle count reading and store those values

  2. Display of PCB ON/OFF status

  3. Live status message. Clamping / unclamp

  4. Clamp done / Unclamp done status to be shown

  5. Pause option outside the URCap (since it stops the entire robot program and prevents output control until resumed)

We have tried using the Realtime Client (port 30003) as a workaround to fetch live robot data, but this has not shown positive results for our application.

Could you kindly advise us on:

  • Whether there is an official or recommended method to fetch and display live input/output status on the URCap UI?

  • If Realtime Client is not suitable, are there alternative supported approaches (e.g., Secondary Client, XML-RPC, or other communication methods)?

Your guidance will help us move forward with providing a better user experience in our URCap.

Thank you for your time and support. We look forward to your valuable suggestions.

I never needed it myself, but I would start with

api.getInstallationAPIProvider().getInstallationAPI().getIOModel().getIOs(DigitalIO.class);

digitalIO.getValue();

there are workarounds if this does not work

we tried it many options, we really want below confirmation.

Could you kindly advise us on:

  • Whether there is an official or recommended method to fetch and display live input/output status on the URCap UI?

  • If Realtime Client is not suitable, are there alternative supported approaches (e.g., Secondary Client, XML-RPC, or other communication methods)?

package com.yourcompany.yourproject;

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;

/*
 * A library class for getting the IO on the robot
 */

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;
	}

}

Above is a class I’ve found on the forum…somewhere which allows you to get the digitalIO IN JAVA. You can call .setValue and .getValue to change and read the variable state FROM THE UI.
Note if you’re trying to read states in realtime, it is on you to employ a thread to call the .getValue() method and take some action accordingly

//Instantiate an instance of the helper by passing it a reference to the IOModel. This example is from the toolbar.
ioHelper = new IOHelper(context.getAPIProvider().getApplicationAPI().getIOModel());
//Assign digital_out[1] to the java variable "yourOutput". It is of type DigitalIO
yourOutput = ioHelper.getSpecificDigitalIO("digital_out[1]");

I reference the below post for which string to feed into the “getSpecificDigitalIO()” method:

Thank you. We will check and get back to you.

We found the above errors while compile the file from JAVA. Please advise is there any other alternative option or else what we could follow to show the external inputs in the teach pendant display.

It’s telling you right there both what the problem is, and how to fix it. In your Timer.fireActionPerformed() on line 313 you’re either modifying the Program Tree via node insertion/deletion or you’re storing some value to the datamodel. In order to modify the tree or the data model, you have to do so in an UndoRedoManager. You’ll see this everywhere in the URCAP samples. In this case, the error has nothing to do with specifically trying to use the IO

undoRedoManager.recordChanges(() -> {
    //Your code goes here
});

And you should have an instantiation of the undoRedoManager in the constructor of your node:

UndoRedoManager undoRedoManager = apiProvider.getProgramAPI().getUndoRedoManager();

For whatever reason, the Installation Nodes don’t use the UndoRedoManager. Just a little tip that’s tripped me up in the past when I find myself copy/pasting things to/from the Installation

1 Like