Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseSCADA/Tutorials/EclipseMagazin"

(A simple client)
Line 85: Line 85:
  
 
For every item you want to get updates for, you need a subscription first. The code is pretty straight forward:
 
For every item you want to get updates for, you need a subscription first. The code is pretty straight forward:
 +
 +
<source lang="java">
 +
package org.eclipse.scada.eclipsemagazin;
 +
 +
import java.util.Observable;
 +
import java.util.Observer;
 +
 +
import org.eclipse.scada.core.ConnectionInformation;
 +
import org.eclipse.scada.core.client.AutoReconnectController;
 +
import org.eclipse.scada.core.client.ConnectionFactory;
 +
import org.eclipse.scada.core.client.ConnectionState;
 +
import org.eclipse.scada.core.client.ConnectionStateListener;
 +
import org.eclipse.scada.da.client.Connection;
 +
import org.eclipse.scada.da.client.DataItem;
 +
import org.eclipse.scada.da.client.DataItemValue;
 +
import org.eclipse.scada.da.client.ItemManagerImpl;
 +
 +
public class SampleClient {
 +
 +
        public static void main(String[] args) throws InterruptedException {
 +
                // the ConnectionFactory works a bit like JDBC,
 +
                // every implementation registers itself when its loaded
 +
                // alternatively it is also possible to use the connection
 +
                // directly, but that would mean the code would have to be aware
 +
                // which protocol is used, which is not desirable
 +
                try {
 +
                        Class.forName("org.eclipse.scada.da.client.ngp.ConnectionImpl");
 +
                } catch (ClassNotFoundException e) {
 +
                        System.err.println(e.getMessage());
 +
                        System.exit(1);
 +
                }
 +
 +
                final String uri = "da:ngp://localhost:2102";
 +
 +
                final ConnectionInformation ci = ConnectionInformation.fromURI(uri);
 +
 +
                final Connection connection = (Connection) ConnectionFactory.create(ci);
 +
                if (connection == null) {
 +
                        System.err
 +
                                        .println("Unable to find a connection driver for specified URI");
 +
                        System.exit(1);
 +
                }
 +
 +
                // just print the current connection state
 +
                connection.addConnectionStateListener(new ConnectionStateListener() {
 +
                        @Override
 +
                        public void stateChange(
 +
                                        org.eclipse.scada.core.client.Connection connection,
 +
                                        ConnectionState state, Throwable error) {
 +
                                System.out.println("Connection state is now: " + state);
 +
                        }
 +
                });
 +
 +
                // although it is possible to use the plain connection, the
 +
                // AutoReconnectController automatically connects to the server
 +
                // again if the connection is lost
 +
                final AutoReconnectController controller = new AutoReconnectController(
 +
                                connection);
 +
                controller.connect();
 +
 +
                // although it is possible to subscribe to an item directly,
 +
                // the recommended way is to use the ItemManager, which handles the
 +
                // subscriptions automatically
 +
                final ItemManagerImpl itemManager = new ItemManagerImpl(connection);
 +
 +
                final DataItem dataItem = new DataItem("memory-cell-0", itemManager);
 +
                dataItem.addObserver(new Observer() {
 +
                        @Override
 +
                        public void update(final Observable observable, final Object update) {
 +
                                final DataItemValue div = (DataItemValue) update;
 +
                                System.out.println(div);
 +
                        }
 +
                });
 +
        }
 +
}
 +
</source>

Revision as of 05:35, 22 October 2013

Eclipse SCADA a Tutorial

Abstract

Eclipse SCADA is the attempt to create a modular »construction kit« to create a custom SCADA system. It provides protocol adapters, a middleware to process data coming from devices, common modules which provide general SCADA functions, like alarms & events, historical data recording, UI components to create a HMI and a configuration framework. For all of these functions, implementations already exist, since its predecessor openSCADA. Some of them are quite comprehensive, some still rudimentary, but usable. Most of it is already battle tested, running already in production for years now. With the move to Eclipse, we try to strengthen the M2M efforts of the Eclipse foundation and also hope to benefit from the other projects in this area.

Since we are not completely finished, there is a chance that some things might be different than explained within this article. An updated version of this article (but in English) will be found at http://wiki.eclipse.org/EclipseSCADA/Tutorials/EclipseMagazin)

Introduction

What is SCADA? »SCADA (Supervisory Control and Data Acquisition) is defined as the monitoring and control of technichal processes by means of a computer system.« This definition from the German wikipedia is a pretty succinct way to put it. The predecessor of Eclipse SCADA – openSCADA – was created in 2006 within the context of a project to provide business applications access to legacy hardware with a tight integration between the physical workflow on the plant and its equivalent business representation. To achieve easy integration and platform independence it was decided to build the solution on the Java platform. At this time, a comprehensive SCADA solution was not required, although it was apparent from the start, that many functionality commonly found in SCADA systems would be needed. After analyzing the existent products on the market, it became clear that none of those would fit the bill, either being to expensive, not flexible enough or not with the features required.

Thus the decision was made to create the needed functionality from scratch and gradually open source the parts which were not customer specific. Most of the proprietary source code were protocol adapters for specific hardware, where even some of the protocols were adapted for the customer.

The general idea of it was to create a common protocol, which the business application will use to talk to the connected devices. Each device type would require a protocol adapter, which translates the specific protocol to the openSCADA protocol. This was the first version of the protocol called NET or GMPP. Within openSCADA these adapters are known as »drivers« or »hives«, which represent basically the server interface of openSCADA. A driver commonly runs in a separate process, in that way the driver can be easily restarted if something goes wrong, without taking the whole system with it. The business application will then use the client interface to connect to the drivers. Some of the drivers which were created are:

  • Exec driver (executes shell calls and parses output)
  • JDBC driver (periodically calls database and retrieves or updates values)
  • Modbus driver
  • SNMP driver
  • OPC driver (based on the independently developed Utgard library)
  • Proxy driver (can switch between multiple driver instances)

At the beginning a lot of the additional functionality beyond the simple protocol conversion was added to the hive implementation. This increased the complexity of configuration, and also made it complicated to correctly chain the operations which happen to the value of a tag (in Eclipse SCADA terminology called an »item«). Additionally the consumer had to configure a separate connection to each running driver. This led to the inception of some kind of middleware, we called it the »master server«.

The master server now contains all functions beyond the task of protocol conversion. It is based on an Equinox OSGi container and each block of functionality is running in its own bundle. This way we could move all advanced functionality to the master server, removing the cruft from the drivers. It also provides the opportunity to configure it during runtime, which was not possible with the simple drivers, which have an XML based configuration. Drivers can also be based on the same reconfigurable model, at the moment publicly available are:

  • S7 driver (dave)
  • Modbus

With the move to Eclipse we decided to keep the protocol implementation separate from the actual Eclipse SCADA driver wrapper, analogous to the OPC driver, where the protocol is encapsulated in a fine grained OPC specific API and the OPC driver which is of course openSCADA specific. In the future, we assume, there will be more projects which need a high quality implementation of commonly used protocols, and we don't want to force anyone to use the complete Eclipse SCADA project if only a way to talk to some device is needed. Also it may be possible that because of licensing restrictions, it is not always possible to integrate the driver with Eclipse SCADA. Two instances where we have this problem already, is the SNMP driver and the OPC driver. These can not be part of the Eclipse SCADA distribution because the underlying libraries are not EPL compatible. For this reason, openSCADA will be staying alive and provide those additional features.

The protocol conversion we have talked about so far only involves the data acquisition (DA) part of a SCADA system. Based on that, Eclipse SCADA provides more features:

  • Alarms & Events (AE): handles process alarms, operator actions, responses generated by the system, informational messages, auditing messages
  • Historical Data (HD): deals with recording values (provided by DA) and archiving these for later retrieval
  • Configuration Administration (CA): handles creation of configurations for the server components, reconfiguration of the running system
  • Visual Interface (VI): provides GUI components, based on Draw2D

The separation of the different layers and responsibilities are reflected in our repository structure, as seen in Figure 1.

Figure 1: Eclipse SCADA GIT repositories overview, http://git.eclipse.org/c/eclipsescada/

The OSTC

Originally called the OpenSCADA Test Client, its is now more than that, for instance used to deploy configuration files for master servers. The OSTC also has an integrated test server which can be used for first experiments. Since its migration to the Eclipse infrastructure is not complete yet, this tutorial will use the setup available through the openSCADA project (the latest 1.2 version at http://download.openscada.org/installer/ostc/I/).

I assume, that you installed the OSTC, if you start it, and open the »DA perspective« you should be greeted with a screen as it is shown in figure 2.

Figure 2: The initial DA view of the OSTC

Under connections you can add connections to SCADA servers, but only under the Nodes with the icons: Default File Source stores them within the standard working area, if you install a new version of the OSTC they are lost; User Preferences and System Preferences use both the Java preference API (http://docs.oracle.com/javase/7/docs/technotes/guides/preferences/) to store the connections within the user accessible area or the system area (that one will probably only work if you have admin rights). The other nodes are only different views of existing connections and can not be modified. This is useful if there are a multitude of servers configured. There they are sorted by different criteria.

For now we start the Test Server using the menu item »Start Local Test Server« under »Testing«.

Figure 3: Starting the test server

The next step is to add a connection, these are URLs, in our case this is »da:ngp://localhost:2102«.

Figure 4: Adding the connection

ngp is the protocol, da is the variant of the protocol. The test server is running on port 2102. Now you can connect to the testserver using a double click on the connection. The connection state should change from »CLOSED« to »BOUND«. After that a list of nodes should appear under the connection node.

Figure 5: Browsing a connection

Expand the memory-cell folder and right click on the item »control«, select »Write Operation«, enter »2« as the value and click on »OK«. After that two more items, »0« and »1« should appear right above the control item. You can now drag those two items to the right into the »Real Time List«.

Figure 6: The newly createditems in the real time list

You can now either write a value on the item using the »Write Operation« Dialog, or use the »Signal Generator«. After that the item should have a value. It should also have an attribute »timestamp«. Depending on the implementation an item can have a number of attributes, »timestamp« the only universally available. Although a driver may poll a device for values, within Eclipse SCADA, each change will be propagated in an event oriented fashion. The basic idea is, if the device supplies a timestamp, as it is the case with some PLCs or OPC servers, the timestamp will be the original one from the device. In any other case Eclipse SCADA will generate one. Any value will be of the type Variant, which in turn can contain either: INT32, INT64, DOUBLE, BOOLEAN, STRING or NULL. Any data update will update both the items primary value, as well as the attributes. The server may choose to only send the changed attributes to reduce traffic. This complete set of data is repesented by the class DataItemValue. Our next step is to create a minimal client to retrieve these change events.

Setting up the IDE

You need to have the latest Kepler release with at least the PDE, EMF Tools and Acceleo installed. I recommend to install the »Eclipse IDE for Java and DSL Developers« variant. Check out following repositories (the ones which are marked with server development in the repository overview) and import the projects:

After that there will be still compile errors. The reason for that is, that a bunch of libraries are used from the Orbit repository. To fix this, have a look at the target platform definition at the org.eclipse.scada.external-target project and set this at the target platform. Probably Eclipse will also complain that no API baseline is set. Use the quick fix to correct this problem, and just use the eclipse installation itself as the reference.

A simple client

For every item you want to get updates for, you need a subscription first. The code is pretty straight forward:

package org.eclipse.scada.eclipsemagazin;
 
import java.util.Observable;
import java.util.Observer;
 
import org.eclipse.scada.core.ConnectionInformation;
import org.eclipse.scada.core.client.AutoReconnectController;
import org.eclipse.scada.core.client.ConnectionFactory;
import org.eclipse.scada.core.client.ConnectionState;
import org.eclipse.scada.core.client.ConnectionStateListener;
import org.eclipse.scada.da.client.Connection;
import org.eclipse.scada.da.client.DataItem;
import org.eclipse.scada.da.client.DataItemValue;
import org.eclipse.scada.da.client.ItemManagerImpl;
 
public class SampleClient {
 
        public static void main(String[] args) throws InterruptedException {
                // the ConnectionFactory works a bit like JDBC,
                // every implementation registers itself when its loaded
                // alternatively it is also possible to use the connection
                // directly, but that would mean the code would have to be aware
                // which protocol is used, which is not desirable
                try {
                        Class.forName("org.eclipse.scada.da.client.ngp.ConnectionImpl");
                } catch (ClassNotFoundException e) {
                        System.err.println(e.getMessage());
                        System.exit(1);
                }
 
                final String uri = "da:ngp://localhost:2102";
 
                final ConnectionInformation ci = ConnectionInformation.fromURI(uri);
 
                final Connection connection = (Connection) ConnectionFactory.create(ci);
                if (connection == null) {
                        System.err
                                        .println("Unable to find a connection driver for specified URI");
                        System.exit(1);
                }
 
                // just print the current connection state
                connection.addConnectionStateListener(new ConnectionStateListener() {
                        @Override
                        public void stateChange(
                                        org.eclipse.scada.core.client.Connection connection,
                                        ConnectionState state, Throwable error) {
                                System.out.println("Connection state is now: " + state);
                        }
                });
 
                // although it is possible to use the plain connection, the
                // AutoReconnectController automatically connects to the server
                // again if the connection is lost
                final AutoReconnectController controller = new AutoReconnectController(
                                connection);
                controller.connect();
 
                // although it is possible to subscribe to an item directly,
                // the recommended way is to use the ItemManager, which handles the
                // subscriptions automatically
                final ItemManagerImpl itemManager = new ItemManagerImpl(connection);
 
                final DataItem dataItem = new DataItem("memory-cell-0", itemManager);
                dataItem.addObserver(new Observer() {
                        @Override
                        public void update(final Observable observable, final Object update) {
                                final DataItemValue div = (DataItemValue) update;
                                System.out.println(div);
                        }
                });
        }
}

Back to the top