Live Connect

The live connector enables direct connections to multiple devices, using different protocols. It utilizes the connectors module to estable connections. LiveConnect requires a configuration file to determine which connections should be established. It will automatically map the node names of the connection to the names specified in the JSON configuration file. This can helps to make the LiveConnect interface very similar to the FMUSimulator interface from the simulators module which enables the direct substitution of simulation models with connections to actual devices and thus the deployment of trained algorithms to real applications.

When using the step function, LiveConnect will determine based on the configuration whether additional actions are required to activate or deactivate a system based on specified parameters. Let’s consider the example of a combined heat and power unit (CHP):

The CHP might have its own programmable logic controller (PLC) which can be accessed via Modbus TCP. From this PLC we want to read detailed data regarding the status of the PLC. Additionally, there might be a PLC for building automation which controls the set point of the CHP as well as the pumps and valves of the hydraulic system. We want to control the CHP with set points provided by an algorithm. This data must be written to the building automation PLC. However, before the CHP can be activated, we need to ensure that the pumps are running and the valves are opened correctly. All of this can be achieved with the LiveConnect configuration. When the class is configured correctly, we only need to call the step function and everything will be done automatically.

For the example we need to configure the system CHP. It has two separate servers, the PLC of the CHP itself, which is a modbus server and the PLC of the building automation, which is an OPC UA server. Both need to be configured accordingly. Once this is done, the different nodes can be configured. For example we can configure nodes for reading from the CHP, nodes for writing to the building automation and other nodes which are used to check the current status of the system.

class eta_utility.connectors.LiveConnect(nodes: Sequence[Node], name: str | None = None, step_size: TimeStep = 1, max_error_count: int = 10, *, init: Mapping[str, Any] | None = None, activate: Mapping[str, Any] | None = None, deactivate: Mapping[str, Any] | None = None, close: Mapping[str, Any] | None = None, observe: Sequence[str] | None = None, activation_indicators: Mapping[str, Any] | None = None, set_values: Mapping[str, Mapping[str, Any] | None] | None = None)[source]

Connect to a system/resource and enable system activation, deactivation and configuring controller setpoints.

The class can be initialized directly by supplying all required arguments or from a JSON configuration file.

If initializing with the from_json classmethod, the class takes a JSON config file which defines all required nodes. The JSON file should have the following format:

  • system: Define the system to be controlled. This is the top level block - it may have multiple dictionary members which should each specify all the following information. If there are multiple systems, all node names will be prefixed with the system name. For example, if the system name is ‘chp’ and the node name is ‘op_request’, the full node name will be ‘chp.op_request’.

  • name: A name to uniquely identify the system.

  • servers: Servers which are responsible for manageing the system. This section should contain a dictionary of servers, identified by a unique name. Each server has the following values:

    • url: URL of the server (format: netloc:port, without the scheme).

    • protocol: Protocol for the connection, for example ‘opcua’.

    • usr: Username to identify with the server (default: None).

    • pwd: Password to log in to the server (default: None).

  • nodes: The nodes section contains a list of nodes. Each node is specific to one of the servers specified above and has a unique name, by which it can be identified. In detail, each node has the following values:

    • name: A name to uniquely identify the node.

    • server: Identifier of one of the servers defined above.

    • dtype: Data type of the Node on the server (default: float).

    • Other values must be defined depending on the protocol, for example this could be an opc_id or corresponding values to identify modbus nodes. More detail about this can be found in connectors.Nodes.

  • set_value: The set_value is the main value, which should be manipulated. It must have some additional information to be processed correctly. This includes:

    • name: Name of the node, which is manipulated as the set_value.

    • min: Minimum value to be allowed.

    • max: Maximum value to be allowed.

    • threshold: Activation/Deactivation threshold. The activate action will be executed for values above the threshold and the deactivation action will be executed for values below the threshold (see below).

    • add: Scale the set_value by adding a set amount.

    • mult: Scale the set_value by multiplying by this factor.

  • activation_indicators: The values specified in this section are used to determine, whether the system is currently active. This is a dictionary of nodes and values, these nodes should be compared against. Each node is identified by the name specified above. Each node must have the following values:

    • compare: Comparison operation to perform (for example ‘==’ or ‘<=’).

    • value: Value to compare against. If the result of all comparisons is True, the system is considered to be currently active.

  • observe: Values to return after each set operation. This is just a list of node names as specified in the nodes section above.

  • actions: In the actions section, default values for more complex operations are specified. For example, if a system needs to be initialized or deactivated. Each of the actions is a dictionary of node names and corresponding values, for example {node1: true, node2: 0.2}. The following actions are defined:

    • init: Initialize the system. This is used to make sure that the system is ready to receive control values from the connector.

    • activate: Activate the system. This is used to set the system to an active state, for example by requesting the system to start its operation and choosing and operating mode. This can be used to set the system up to receive more detailed control values.

    • deactivate: Execute any actions to deactivate the system.

    • close: Reset the system. This is used when the connector is closed, to make sure the system is left in a safe and clean state.

If initializing manually, each of the actions and some other information must be specified as parameters to the class. This way, the class will not automatically identify different systems and will instead assume that all parameters belong to the same system. If system differentiation is required, the node prefixing must be done manually. The third option is to initialize from a dictionary using the from_dict function. This works equivalent to the from_json function.

Warning

Always call the close function after you are done using the connection! This is required even if no nodes must be written to reset the system since the connection itself must be closed. Therefore, this class should only be called within a try-finally clause. Alternatively the class can be used as a context manager in a with statement.

Parameters:
  • name – Name to uniquely identify the system. The name is also used as the default system prefix.

  • nodes – Sequence/List of Nodes, which should be used for the actions and for initializing connections.

  • step_size – Step size (time) for the live connector in time increments.

  • init – Nodes for initializing the system (see above).

  • activate – Nodes for activating the system (see above).

  • deactivate – Nodes for deactivating the system (see above).

  • close – Nodes to close the connection and reset the system (see above).

  • observe – Nodes to read from and return after each ‘set’ operation (see above).

  • activation_indicators – Nodes that determine, whether the system must be deactivated or activated. This is used internally in conjunction with the set_value threshold to determine whether the activate/deactivate methods must be called before setting values.

  • set_values – Specification of the node which is used for setting the main control value.

name: str | None

Name of the system.

start_time

Start time of initialisation.

step_size

Step size (time) for the live connector in time increments.

steps_counter: int

Current step of the live connector (number of completed steps).

max_error_count: int

Maximum error count when connections in read/write function are aborted.

error_count: list[int]

Counts the number of errors when Live Connector logs errors.

classmethod from_json(files: Path | Sequence[Path], usr: str | None = None, pwd: str | None = None, step_size: TimeStep = 1, max_error_count: int = 10) LiveConnect[source]

Initialize the connection directly from JSON configuration files. The file should contain parameters as described above. A list of file names can be supplied to enable the creation of larger, combined systems.

Username and password supplied as keyword arguments will take precedence over information given in the config file.

Parameters:
  • files – Configuration file paths. Accepts a single file or a list of files.

  • usr – Username for authentication with the resource.

  • pwd – Password for authentication with the resource.

  • step_size – Step size (time) for the live connector in time increments.

Returns:

LiveConnect instance as specified by the JSON file.

classmethod from_dict(usr: str | None = None, pwd: str | None = None, step_size: TimeStep = 1, max_error_count: int = 10, **config: Any) LiveConnect[source]

Initialize the connection directly from a config dictionary. The dictionary should contain parameters as described above.

Username and password supplied as keyword arguments will take precedence over information given in the config file.

Parameters:
  • usr – Username for authentication with the resource.

  • pwd – Password for authentication with the resource.

  • step_size – Step size (time) for the live connector in time increments.

  • config – Configuration dictionary.

Returns:

LiveConnect instance as specified by the JSON file.

property nodes: Mapping[str, Node]

Mapping of all node objects of the connection.

step(value: Mapping[str, Any]) dict[str, Any][source]

Take the set_value and determine, whether the system must be activated or deactivated. Then set the value and finally read and return all values as specified by the ‘observe’ parameter.

Parameters:

value – Value to use as the control value/set_value.

Returns:

Values read from the connection as specified by ‘observe’ parameter.

write(nodes: Mapping[str, Any] | Sequence[str], values: Sequence[Any] | None = None) None[source]

Write any combination of nodes and values.

Parameters:
  • nodes – Mapping of Nodes and values or Sequence of node names to write to.

  • values – If nodes are given as a Sequence, this second parameter determined the values to be written. If nodes are given as a Mapping, this parameter is not required. It defaults to None.

read(*nodes: str) dict[str, Any][source]

Take a list of nodes and return their names and most recent values.

Parameters:

nodes – One or more nodes to read.

Returns:

Dictionary of the most current node values.

activate(system: str | None = None) None[source]

Take the list of nodes to activate and set them to the correct values to activate the system.

Parameters:

system – System for which should be activated (default: self.name).

deactivate(system: str | None = None) None[source]

Take the list of nodes to deactivate and set them to the correct values to deactivate the system.

Parameters:

system – System for which should be activated (default: self.name).

close() None[source]

Reset the system and close the connection.