Custom IDL Interfaces
REDHAWK provides Front End Interfaces (FEI) and standard Core Framework (CF) interfaces (like CF::Resource) to control entities and promote interoperability. There are some use cases where you may find the need to use custom Interface Description Language (IDL) to control entities. For these use cases, you can create custom IDL projects in the IDE.
Adding ports from either the FEI interface or a custom IDL interface to a component or device allows that entity to control other entities through CORBA. Because of the generic nature of these ports, it is not possible to create a language mapping like BulkIO, so interaction is through the standard CORBA API, a full description of which is outside the scope of this manual. However, the REDHAWK code generators will generate ports that simplify the interaction with the port. The following sections explain uses (output) ports because they are the most likely to be generated, for example, to control FEI devices.
Connectivity Feedback
In all three supported languages, an FEI, standard CF, or custom IDL port will have all methods and attributes mapped to the port, and the port will then delegate the call to the remote connection. In REDHAWK, it is possible for a port to have no connections, one connection, or many connections. Each of these conditions can create issues for someone using a port for communications; for example, if a control request is sent out and there are no connections, then the user should be informed that the request did not go anywhere.
At the same time, not all methods are the same. Some methods push data in only one direction, some methods have a return value, and some methods have arguments that are pointers to be filled with information (out or inout arguments). When a port method is called and it is not possible for the port to make a call or for the call to be unambiguous (for example, if two connections exist and the function contains a return value), then a PortCallError is raised in the user code. The table below describes the method signature criteria met and its corresponding behavior.
Control method and error conditions based on connectivity
method return value | argument direction | specified Connection ID | no connection | one connection | many connections |
---|---|---|---|---|---|
void | in only | None | ok | ok | ok |
Non void | in only | None | Error | ok | Error |
All types | in only | valid ID | Error | ok | ok |
All types | inout and/or out | None | Error | ok | Error |
All types | inout and/or out | valid ID | Error | ok | ok |
All types | any direction | invalid ID | Error | Error | Error |
If a method has any kind of return value as part of its non-exception API (manifested as a non-void return value, or an out or inout argument), then an exception is raised if there is more than one connection out of the port. Furthermore, if a call is attempted with no connection in effect, an error is raised.
Connection Selection
While the generated port class triggers an error when the desired connection is ambiguous, it also contains an API to allow the developer to select which connection should be exercised. Each method has an optional argument, connection_id
, that allows the caller to disambiguate which connection should be exercised. The default value behavior will use the last connection made. If the connection_id
specified does not exist, a PortCallError
will be raised.
In the following sections, the same pattern used to disambiguate the connections is provided in all three supported languages.
The following code example uses the default behavior when calling the read method of the CF::File interface.
CF::OctetSequence_var _data = new CF::OctetSequence();
CF::OctetSequence_out data(_data);
this->file_out->read(data, 10); // read 10 characters from the last connection made to the port
The following code example disambiguates the read call to a specific connection, connection1
.
CF::OctetSequence_var _data = new CF::OctetSequence();
CF::OctetSequence_out data(_data);
this->file_out->read(data, 10, "connection1"); // read 10 characters from the connection called "connection1"
To view the connections that are available, use the following code:
std::vector<std::string> _connection_ids = this->file_out->getConnectionIds();
Method Mapping
Method name mapping follows the pattern described in Connection Selection; namely that methods have the same name as described in the IDL with an additional argument (to be optionally exercised) that can specify which connection should be used. Attributes are mapped as functions to the CORBA objects. REDHAWK provides additional APIs to disambiguate these calls for multiple connections.
Reading Attributes
Reading attributes is performed by invoking the name of the attribute as a function. For example, if the port, my_port
, contains the string attribute greeting
, the value of greeting
can be retrieved as follows:
std::string _greeting = this->my_port->greeting();
To retrieve the value from a specific connection, the _get_
prefix is needed:
std::string _greeting = this->my_port->_get_greeting("some_connection_name");
Writing Attributes
Writing attributes in C++ and Java involves invoking the function with the appropriate argument:
this->my_port->greeting("hello"); // write "hello" to the attribute "greeting"
this->my_port->greeting("hello", "some_connection_name"); // write "hello" to the attribute "greeting" over connection "some_connection_name"
Python requires the prefix _set_
because it cannot be overloaded:
self.my_port._set_greeting("hello") # write "hello" to the attribute "greeting"
self.my_port._set_greeting("hello", "some_connection_name") # write "hello" to the attribute "greeting" over connection "some_connection_name"