Monday, February 22, 2021

Sample OPC client using OPC .Net API

 OPC Classic is a common platform/specification implemented in industrial applications. This includes SCADA (supervisory control and data acquisition) and DCS (distributed control systems), building management packages, discrete manufacturing solutions, etc. DCS systems including DeltaV from Emerson, Experion LX from Honeywell, Centum VP from Yokogawa are just few of the big names that implements OPC.

OPC Foundation provides redistributables that can be used to implement OPC clients for free. Access to specifications, sample servers and clients need paid membership to download from the foundation. 

 Create an account in OPC Foundation to download OPC Core Components Redistributables,  As of this writing (2/23/20201) the version available is 3.00.108. Once downloaded, extract the zip file and run OPC Core Components Redistributable (x64) 3.00.108.msi. Note that you may have to remove alternate streams from the downloaded zip file, see this link.Among other things, the installer should have installed nuget packages in C:\Program Files (x86)\OPC Foundation\NuGetPackages, mine looks like below.

Figure 1. Nuget packages

 Assuming you have Visual Studio 2019, if not you can download a trial or community edition from here, create a new C# .Net Framework console application like below. 

Figure 2. Project type

 
Figure 3. Project name and .Net Framework target

Add OPC Foundation Nuget packages via Tools | Options... menu. It should look like below.

Figure 4. OPC Nuget package in Visual Studio

With Nuget package local store added, add them to the project, like:

Figure 5. Bring up Manage Nuget Packages...

Figure 6. Install all 4 packages


Figure 7. Solution explorer shows the 4 packages added to the project

Now add the following code to your main project.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace testopcclient

{

    class Program

    {

        static void Main(string[] args)

        {

            string hostname = "M6"; //machine name or IP

            Opc.URL url = new Opc.URL($"opcda://{hostname}/OPC.DeltaV.1");

            var opc_item = new Opc.Da.Item(new Opc.ItemIdentifier("TESTMOD/SGGN1/OUT.CV"));

            Opc.Da.Server server = new Opc.Da.Server(new OpcCom.Factory(), url);

            server.Connect(new Opc.ConnectData(null, null));


            Console.WriteLine("Esc key to exit");

            do

            {

                while (!Console.KeyAvailable)

                {

                    var result = server.Read(new Opc.Da.Item[] { opc_item });

                    Console.WriteLine($"{result[0].ItemName}:{result[0].Value}");

                    System.Threading.Thread.Sleep(1000);

                }

            } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            server.Disconnect();

            Console.WriteLine("This should close connection to the server, key to continue");

            Console.ReadKey(true);

        }

    }

}

This assumes that you are using DeltaV OPC Server on machine M6 and that it has a control module with SGGN block generating data.

Have fun!

Sunday, September 6, 2020

Pure Java OPC DA sample client

 

Using pure Java OPC library allows you to run the client on any OS that supports Java. For this blog I will show you a sample client using OpenScada library. 


You need the following tools and components to run this example:

IDE: IntelliJ IDEA Community Edition 2020.2

OPC Server: Matrikon Simulation Server 

Libraries:

Library

Version

https://mvnrepository.com/artifact/org.openscada.utgard/org.openscada.opc.dcom

1.5.0

https://mvnrepository.com/artifact/org.openscada.utgard/org.openscada.opc.lib

1.5.0

https://mvnrepository.com/artifact/org.openscada.jinterop/org.openscada.jinterop.core

2.1.8

https://mvnrepository.com/artifact/org.openscada.external/org.openscada.external.jcifs

1.2.25

https://mvnrepository.com/artifact/org.openscada.jinterop/org.openscada.jinterop.deps

1.5.0

https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on

1.66

https://mvnrepository.com/artifact/org.slf4j/slf4j-simple

1.7.30

Java: Java JDK 1.8 or later


To create a sample client, do:

  1. Open IntelliJ IDEA Community Edition

  2. Do File | New | Project…

  3. Select Maven, then set Project SDK, I am using Open JDK 11 on Ubuntu 20.04 (sudo apt install openjdk-11-jdk), then do Next

  4. Set project details like testopc

  5. See below for pom.xml, copy/paste and do Load Maven Changes or Ctrl+Shift+o

  6. Navigate to Project | testopc | src | main | java, then do File | New | Java Class. Name the class client for example and copy client.java below. 

  7. Update client.java for the username and password

  8. Then run it


Pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>

 

   <groupId>org.example</groupId>

   <artifactId>testopc</artifactId>

   <version>1.0-SNAPSHOT</version>

   <build>

       <plugins>

           <plugin>

               <groupId>org.apache.maven.plugins</groupId>

               <artifactId>maven-compiler-plugin</artifactId>

               <configuration>

                   <source>6</source>

                   <target>6</target>

               </configuration>

           </plugin>

       </plugins>

   </build>

 

   <dependencies>

       <dependency>

           <groupId>org.openscada.utgard</groupId>

           <artifactId>org.openscada.opc.dcom</artifactId>

           <version>1.5.0</version>

       </dependency>

       <dependency>

           <groupId>org.openscada.utgard</groupId>

           <artifactId>org.openscada.opc.lib</artifactId>

           <version>1.5.0</version>

       </dependency>

       <dependency>

           <groupId>org.openscada.jinterop</groupId>

           <artifactId>org.openscada.jinterop.core</artifactId>

           <version>2.1.8</version>

       </dependency>

       <dependency>

           <groupId>org.openscada.external</groupId>

           <artifactId>org.openscada.external.jcifs</artifactId>

           <version>1.2.25</version>

       </dependency>

       <dependency>

           <groupId>org.openscada.jinterop</groupId>

           <artifactId>org.openscada.jinterop.deps</artifactId>

           <version>1.5.0</version>

       </dependency>

       <dependency>

           <groupId>org.bouncycastle</groupId>

           <artifactId>bcprov-jdk15on</artifactId>

           <version>1.66</version>

       </dependency>

       <dependency>

           <groupId>org.slf4j</groupId>

           <artifactId>slf4j-simple</artifactId>

           <version>1.7.30</version>

       </dependency>

   </dependencies>

</project>


Client.java

import org.jinterop.dcom.common.JIException;

import org.jinterop.dcom.common.JISystem;

import org.openscada.opc.lib.common.ConnectionInformation;

import org.openscada.opc.lib.da.*;

import java.util.concurrent.Executors;

import java.util.logging.Level;

import java.util.logging.LogManager;

 

public class client {

   public static void main(String[] args) throws Exception {

       JISystem.setInBuiltLogHandler(false);

       LogManager logManager = LogManager.getLogManager();

       logManager.getLogger("org.jinterop").setLevel(Level.FINEST);

       JISystem.setAutoRegisteration(true);

 

       final ConnectionInformation ci = new ConnectionInformation();

       ci.setHost("192.168.0.30");

       ci.setDomain("");

       ci.setUser("user1");

       ci.setPassword("password1");

       ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305"); //Matrikon

       final String itemId = "Saw-toothed Waves.Int2"; //Matrikon

 

       // create a new server

       final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());

 

       try {

           // connect to server

           server.connect();

           // add sync access, poll every 500 ms

           final AccessBase access = new SyncAccess(server, 500);

           access.addItem(itemId, new DataCallback() {

               @Override

               public void changed(Item item, ItemState state) {

                   System.out.println(state);

               }

           });

           // start reading

           access.bind();

           // wait a little bit

           Thread.sleep(10 * 1000);

           // stop reading

           access.unbind();

       } catch (final JIException e) {

           System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));

       }

   }

}


REF:01

Sample OPC client using OPC .Net API

  OPC Classic is a common platform/specification implemented in industrial applications. This includes SCADA (supervisory control and data ...