All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zaber.motion.binary.Connection Maven / Gradle / Ivy

Go to download

A library that aims to provide easy-to-use API for communication with Zaber devices using Zaber ASCII Protocol.

There is a newer version: 6.7.0
Show newest version
// ===== THIS FILE IS GENERATED FROM A TEMPLATE ===== //
// ============== DO NOT EDIT DIRECTLY ============== //

package zaber.motion.binary;

import zaber.motion.protobufs.Main;
import zaber.motion.gateway.Call;
import zaber.motion.gateway.Events;
import zaber.motion.exceptions.ExceptionConverter;
import zaber.motion.exceptions.MotionLibException;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import io.reactivex.Observable;
import io.reactivex.subjects.ReplaySubject;
import io.reactivex.subjects.Subject;

/**
 * Class representing access to particular connection (serial port, TCP connection) using the legacy Binary protocol.
 */
public class Connection implements AutoCloseable {

    private Observable unknownResponse;

    /**
     * Event invoked when a response from a device cannot be matched to any known request.
     */
    public Observable getUnknownResponse() {
        return this.unknownResponse;
    }

    private Observable replyOnly;

    /**
     * Event invoked when a reply-only command such as a move tracking message is received from a device.
     */
    public Observable getReplyOnly() {
        return this.replyOnly;
    }

    private Subject disconnected = ReplaySubject.create();

    /**
     * Event invoked when connection is interrupted or closed.
     */
    public Observable getDisconnected() {
        return this.disconnected;
    }

    /**
     * Default baud rate for serial connections.
     */
    public static final int DEFAULT_BAUD_RATE = 9600;


    private int interfaceId;

    /**
     * @return The interface ID identifies thisConnection instance with the underlying library.
     */
    public int getInterfaceId() {
        return this.interfaceId;
    }

    public Connection(
        int interfaceId) {
        this.interfaceId = interfaceId;
        this.subscribe();
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @param baudRate Optional baud rate (defaults to 9600).
     * @param useMessageIds Enable use of message IDs (defaults to disabled).
     * All your devices must be pre-configured to match.
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the port.
     */
    public static CompletableFuture openSerialPortAsync(
        String portName, int baudRate, boolean useMessageIds) {
        Main.OpenBinaryInterfaceRequest.Builder builder = Main.OpenBinaryInterfaceRequest.newBuilder();
        builder = builder.setInterfaceType(Main.InterfaceType.SERIAL_PORT);

        builder = builder.setPortName(portName);
        builder = builder.setBaudRate(baudRate);
        builder = builder.setUseMessageIds(useMessageIds);
        CompletableFuture response = Call.callAsync(
            "binary/interface/open",
            builder.build(),
            Main.OpenInterfaceResponse.parser());
        return response
            .thenApply(r -> new Connection(r.getInterfaceId()));
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @param baudRate Optional baud rate (defaults to 9600).
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the port.
     */
    public static CompletableFuture openSerialPortAsync(
        String portName, int baudRate) {
        return openSerialPortAsync(portName, baudRate, false);
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the port.
     */
    public static CompletableFuture openSerialPortAsync(
        String portName) {
        return openSerialPortAsync(portName, DEFAULT_BAUD_RATE, false);
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @param baudRate Optional baud rate (defaults to 9600).
     * @param useMessageIds Enable use of message IDs (defaults to disabled).
     * All your devices must be pre-configured to match.
     * @return An object representing the port.
     */
    public static Connection openSerialPort(
        String portName, int baudRate, boolean useMessageIds) {
        try {
            return openSerialPortAsync(portName, baudRate, useMessageIds).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @param baudRate Optional baud rate (defaults to 9600).
     * @return An object representing the port.
     */
    public static Connection openSerialPort(
        String portName, int baudRate) {
        return openSerialPort(portName, baudRate, false);
    }

    /**
     * Opens a serial port.
     * @param portName Name of the port to open.
     * @return An object representing the port.
     */
    public static Connection openSerialPort(
        String portName) {
        return openSerialPort(portName, DEFAULT_BAUD_RATE, false);
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @param port Optional port number (defaults to 8657).
     * @param useMessageIds Enable use of message IDs (defaults to disabled).
     * All your devices must be pre-configured to match.
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the connection.
     */
    public static CompletableFuture openTcpAsync(
        String hostName, int port, boolean useMessageIds) {
        Main.OpenBinaryInterfaceRequest.Builder builder = Main.OpenBinaryInterfaceRequest.newBuilder();
        builder = builder.setInterfaceType(Main.InterfaceType.TCP);

        builder = builder.setHostName(hostName);
        builder = builder.setPort(port);
        builder = builder.setUseMessageIds(useMessageIds);
        CompletableFuture response = Call.callAsync(
            "binary/interface/open",
            builder.build(),
            Main.OpenInterfaceResponse.parser());
        return response
            .thenApply(r -> new Connection(r.getInterfaceId()));
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @param port Optional port number (defaults to 8657).
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the connection.
     */
    public static CompletableFuture openTcpAsync(
        String hostName, int port) {
        return openTcpAsync(hostName, port, false);
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @return A CompletableFuture that can be completed to get the result:
     * An object representing the connection.
     */
    public static CompletableFuture openTcpAsync(
        String hostName) {
        return openTcpAsync(hostName, 0, false);
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @param port Optional port number (defaults to 8657).
     * @param useMessageIds Enable use of message IDs (defaults to disabled).
     * All your devices must be pre-configured to match.
     * @return An object representing the connection.
     */
    public static Connection openTcp(
        String hostName, int port, boolean useMessageIds) {
        try {
            return openTcpAsync(hostName, port, useMessageIds).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @param port Optional port number (defaults to 8657).
     * @return An object representing the connection.
     */
    public static Connection openTcp(
        String hostName, int port) {
        return openTcp(hostName, port, false);
    }

    /**
     * Opens a TCP connection.
     * @param hostName Hostname or IP address.
     * @return An object representing the connection.
     */
    public static Connection openTcp(
        String hostName) {
        return openTcp(hostName, 0, false);
    }

    /**
     * Close the connection.
     * @return A CompletableFuture that can be completed to know when the work is complete.
     */
    public CompletableFuture closeAsync() {
        Main.CloseInterfaceRequest.Builder builder = Main.CloseInterfaceRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        return Call.callAsync("interface/close", builder.build(), null)
            .thenApply(r -> (Void) null);
    }

    /**
     * Close the connection.
     */
    public void close() {
        try {
            closeAsync().get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for a response from the device. 0 or negative defaults to 0.5s.
     * @param checkErrors Controls whether to throw an exception when the device rejects the command.
     * @return A CompletableFuture that can be completed to get the result:
     * A response to the command.
     */
    public CompletableFuture genericCommandAsync(
        int device, CommandCode command, int data, double timeout, boolean checkErrors) {
        Main.GenericBinaryRequest.Builder builder = Main.GenericBinaryRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        builder = builder.setDevice(device);
        builder = builder.setCommand(command.getValue());
        builder = builder.setData(data);
        builder = builder.setTimeout(timeout);
        builder = builder.setCheckErrors(checkErrors);
        CompletableFuture response = Call.callAsync(
            "binary/interface/generic_command",
            builder.build(),
            Main.BinaryMessage.parser());
        return response
            .thenApply(r -> Message.fromProtobuf(r));
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for a response from the device. 0 or negative defaults to 0.5s.
     * @return A CompletableFuture that can be completed to get the result:
     * A response to the command.
     */
    public CompletableFuture genericCommandAsync(
        int device, CommandCode command, int data, double timeout) {
        return genericCommandAsync(device, command, data, timeout, true);
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @return A CompletableFuture that can be completed to get the result:
     * A response to the command.
     */
    public CompletableFuture genericCommandAsync(
        int device, CommandCode command, int data) {
        return genericCommandAsync(device, command, data, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @return A CompletableFuture that can be completed to get the result:
     * A response to the command.
     */
    public CompletableFuture genericCommandAsync(
        int device, CommandCode command) {
        return genericCommandAsync(device, command, 0, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for a response from the device. 0 or negative defaults to 0.5s.
     * @param checkErrors Controls whether to throw an exception when the device rejects the command.
     * @return A response to the command.
     */
    public Message genericCommand(
        int device, CommandCode command, int data, double timeout, boolean checkErrors) {
        try {
            return genericCommandAsync(device, command, data, timeout, checkErrors).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for a response from the device. 0 or negative defaults to 0.5s.
     * @return A response to the command.
     */
    public Message genericCommand(
        int device, CommandCode command, int data, double timeout) {
        return genericCommand(device, command, data, timeout, true);
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @return A response to the command.
     */
    public Message genericCommand(
        int device, CommandCode command, int data) {
        return genericCommand(device, command, data, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @return A response to the command.
     */
    public Message genericCommand(
        int device, CommandCode command) {
        return genericCommand(device, command, 0, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection without expecting a response.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @return A CompletableFuture that can be completed to know when the work is complete.
     */
    public CompletableFuture genericCommandNoResponseAsync(
        int device, CommandCode command, int data) {
        Main.GenericBinaryRequest.Builder builder = Main.GenericBinaryRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        builder = builder.setDevice(device);
        builder = builder.setCommand(command.getValue());
        builder = builder.setData(data);
        return Call.callAsync("binary/interface/generic_command_no_response", builder.build(), null)
            .thenApply(r -> (Void) null);
    }

    /**
     * Sends a generic Binary command to this connection without expecting a response.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @return A CompletableFuture that can be completed to know when the work is complete.
     */
    public CompletableFuture genericCommandNoResponseAsync(
        int device, CommandCode command) {
        return genericCommandNoResponseAsync(device, command, 0);
    }

    /**
     * Sends a generic Binary command to this connection without expecting a response.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     */
    public void genericCommandNoResponse(
        int device, CommandCode command, int data) {
        try {
            genericCommandNoResponseAsync(device, command, data).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Sends a generic Binary command to this connection without expecting a response.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param device Device address to send the command to. Use zero for broadcast.
     * @param command Command to send.
     */
    public void genericCommandNoResponse(
        int device, CommandCode command) {
        genericCommandNoResponse(device, command, 0);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for all responses from the device chain. 0 or negative defaults to 0.5s.
     * @param checkErrors Controls whether to throw an exception when any device rejects the command.
     * @return A CompletableFuture that can be completed to get the result:
     * All responses to the command.
     */
    public CompletableFuture genericCommandMultiResponseAsync(
        CommandCode command, int data, double timeout, boolean checkErrors) {
        Main.GenericBinaryRequest.Builder builder = Main.GenericBinaryRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        builder = builder.setCommand(command.getValue());
        builder = builder.setData(data);
        builder = builder.setTimeout(timeout);
        builder = builder.setCheckErrors(checkErrors);
        CompletableFuture response = Call.callAsync(
            "binary/interface/generic_command_multi_response",
            builder.build(),
            Main.BinaryMessageCollection.parser());
        return response
            .thenApply(r -> r.getMessagesList().stream()
            .map(resp -> Message.fromProtobuf(resp)).toArray(Message[]::new));
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for all responses from the device chain. 0 or negative defaults to 0.5s.
     * @return A CompletableFuture that can be completed to get the result:
     * All responses to the command.
     */
    public CompletableFuture genericCommandMultiResponseAsync(
        CommandCode command, int data, double timeout) {
        return genericCommandMultiResponseAsync(command, data, timeout, true);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @return A CompletableFuture that can be completed to get the result:
     * All responses to the command.
     */
    public CompletableFuture genericCommandMultiResponseAsync(
        CommandCode command, int data) {
        return genericCommandMultiResponseAsync(command, data, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @return A CompletableFuture that can be completed to get the result:
     * All responses to the command.
     */
    public CompletableFuture genericCommandMultiResponseAsync(
        CommandCode command) {
        return genericCommandMultiResponseAsync(command, 0, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for all responses from the device chain. 0 or negative defaults to 0.5s.
     * @param checkErrors Controls whether to throw an exception when any device rejects the command.
     * @return All responses to the command.
     */
    public Message[] genericCommandMultiResponse(
        CommandCode command, int data, double timeout, boolean checkErrors) {
        try {
            return genericCommandMultiResponseAsync(command, data, timeout, checkErrors).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @param timeout Number of seconds to wait for all responses from the device chain. 0 or negative defaults to 0.5s.
     * @return All responses to the command.
     */
    public Message[] genericCommandMultiResponse(
        CommandCode command, int data, double timeout) {
        return genericCommandMultiResponse(command, data, timeout, true);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @param data Optional data argument to the command. Defaults to zero.
     * @return All responses to the command.
     */
    public Message[] genericCommandMultiResponse(
        CommandCode command, int data) {
        return genericCommandMultiResponse(command, data, 0.0, true);
    }

    /**
     * Sends a generic Binary command to this connection and expects responses from one or more devices.
     * Responses are returned in order of arrival.
     * For more information please refer to the
     * [Binary Protocol Manual](https://www.zaber.com/protocol-manual?protocol=Binary#topic_quick_command_reference).
     * @param command Command to send.
     * @return All responses to the command.
     */
    public Message[] genericCommandMultiResponse(
        CommandCode command) {
        return genericCommandMultiResponse(command, 0, 0.0, true);
    }

    /**
     * Renumbers devices present on this connection. After renumbering, you must identify devices again.
     * @return A CompletableFuture that can be completed to get the result:
     * Total number of devices that responded to the renumber.
     */
    public CompletableFuture renumberDevicesAsync() {
        Main.BinaryDeviceRenumberRequest.Builder builder = Main.BinaryDeviceRenumberRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        CompletableFuture response = Call.callAsync(
            "binary/device/renumber",
            builder.build(),
            Main.BinaryDeviceRenumberResponse.parser());
        return response
            .thenApply(r -> r.getNumberDevices());
    }

    /**
     * Renumbers devices present on this connection. After renumbering, you must identify devices again.
     * @return Total number of devices that responded to the renumber.
     */
    public int renumberDevices() {
        try {
            return renumberDevicesAsync().get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Attempts to detect any devices present on this connection.
     * @param identifyDevices Determines whether device identification should be performed as well.
     * @return A CompletableFuture that can be completed to get the result:
     * Array of detected devices.
     */
    public CompletableFuture detectDevicesAsync(
        boolean identifyDevices) {
        Main.BinaryDeviceDetectRequest.Builder builder = Main.BinaryDeviceDetectRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        builder = builder.setIdentifyDevices(identifyDevices);
        CompletableFuture response = Call.callAsync(
            "binary/device/detect",
            builder.build(),
            Main.BinaryDeviceDetectResponse.parser());
        return response
            .thenApply(r -> r.getDevicesList().stream()
            .map(deviceAddress -> this.getDevice(deviceAddress)).toArray(Device[]::new));
    }

    /**
     * Attempts to detect any devices present on this connection.
     * @return A CompletableFuture that can be completed to get the result:
     * Array of detected devices.
     */
    public CompletableFuture detectDevicesAsync() {
        return detectDevicesAsync(true);
    }

    /**
     * Attempts to detect any devices present on this connection.
     * @param identifyDevices Determines whether device identification should be performed as well.
     * @return Array of detected devices.
     */
    public Device[] detectDevices(
        boolean identifyDevices) {
        try {
            return detectDevicesAsync(identifyDevices).get();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MotionLibException) {
                throw (MotionLibException) e.getCause();
            } else {
                throw new MotionLibException(e.getCause());
            }
        } catch (InterruptedException e) {
            throw new MotionLibException(e);
        }
    }

    /**
     * Attempts to detect any devices present on this connection.
     * @return Array of detected devices.
     */
    public Device[] detectDevices() {
        return detectDevices(true);
    }

    /**
     * Gets a Device class instance which allows you to control a particular device on this connection.
     * Devices are numbered from 1.
     * @param deviceAddress Address of device intended to control. Address is configured for each device.
     * @return Device instance.
     */
    public Device getDevice(
        int deviceAddress) {
        if (deviceAddress <= 0) {
            throw new IllegalArgumentException("Invalid value; physical devices are numbered from 1.");
        }
        return new Device(this, deviceAddress);
    }


    /**
     * Returns a string that represents the connection.
     * @return A string that represents the connection.
     */
    public String toString() {
        Main.ToStringRequest.Builder builder = Main.ToStringRequest.newBuilder();
        builder = builder.setInterfaceId(getInterfaceId());

        Main.ToStringResponse response = Call.callSync(
            "interface/to_string",
            builder.build(),
            Main.ToStringResponse.parser());
        return response.getToStr();
    }


    private void subscribe() {
        this.unknownResponse = Events.getEventObservable()
            .takeUntil(this.disconnected)
            .filter(event -> event.getEventName().equals("binary/interface/unknown_response"))
            .map(event -> (Main.UnknownBinaryResponseEvent) event.getEventData())
            .filter(event -> (event.getInterfaceId() == this.interfaceId))
            .map(event -> UnknownResponseEvent.fromProtobuf(event));

        this.replyOnly = Events.getEventObservable()
            .takeUntil(this.disconnected)
            .filter(event -> event.getEventName().equals("binary/interface/reply_only"))
            .map(event -> (Main.BinaryReplyOnlyEvent) event.getEventData())
            .filter(event -> (event.getInterfaceId() == this.interfaceId))
            .map(event -> ReplyOnlyEvent.fromProtobuf(event));

        Events.getEventObservable()
            .filter(event -> event.getEventName().equals("interface/disconnected"))
            .map(event -> (Main.DisconnectedEvent) event.getEventData())
            .filter(event -> (event.getInterfaceId() == this.interfaceId))
            .take(1)
            .map(event -> ExceptionConverter.convert(event.getErrorType(), event.getErrorMessage()))
            .subscribe(this.disconnected);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy