OPCUA Interface - OPCUA4Unity

Introduction

OPCUA is a standard, maintained by the OPC foundation, for industrial communication. Most of the providers of automation devices´, like PLC and Robot manufacturers, are providing OPCUA servers. Sometimes the OPCUA server is directly integrated into the automation device and sometimes a special software neeeds to be installed on a PC. OPCUA is one impotant upcoming standard for Industry4.0.

For more information please check:
https://opcfoundation.org/about/opc-technologies/opc-ua/

This OPCUA client interface for Unity is based on excellent technology from Träger Industry Components (https://www.traeger.de/). Many thanks to Träger for supporing us.

OPCUA4Unity is available as a standalone asset as well as part of Game4Automation Professional. The connection to the behavior models (PLCInputs and PLCOutputs) as well as the display of the Signals in the Hierarchy view is part of the Game4Automation Framework and not available in the OPCUA4Unity standalone asset.

Installation

Both assets, Game4Automation Professional as well as OPCUA4Unity are installed by using the Unity Asset Store.

If you are using the Game4Automation Framework you are finding the OPCUA Interface after the installation under the path game4automation/private/interfaces/OPCUA4Unity If you are using the Standalone version you will find it under the path OPCUA4Unity in the Asset folder.

if you are using the Game4Automation Professional version you can use OPCUA4Unity also independent from Game4Automation. You just need to move the full OPCUA4Unity folder to a new project.

Demo model

In the sub-folder, DemoModel we provide a small demo which is showing you how to use the OPCUA interface independent from the Game4Automation Framework. The demo model is working with a demo OPCUA Demo server (OPC UA C++ Demo Server V1.6.3 (Windows)) from Unified Automation (https://www.unified-automation.com/downloads/opc-ua-servers.html). You can download the OPCUA server for free, if you register before at Unified Automation.

Build settings

Please use these build settings. Mono is also working. Depending on your destination device you might need to use IL2CPP.

Interface Configuration

If you are using Game4Automation you can use the tool-bar to add an OPCUA interface to your scene:

Otherwise you will need to create an empty Gameobject and add the Script OPCUA_Interface to your Gameobject.

For the interface you will need to define at least

Property Description
Server The address of the server, whether on your machine like the demo server or on an external device
Connect To Server true to connect to the server. If false the opcua interface is inactive.
Auto Accept Server Certificates true, will accept all Server certificates. Should be changed to false for productive environments.
Client Auto Generate Certificate true, will generate a Certificate for a client if none is existing under the Certificate Path in the Streaming Assets folder. Should be changed in productive environments.
Use Only Secure Endpoints false for test purposes. If true only secure endpoints are allowed.
Use High Level Endpoint Security false for test purposes. If true always the highest security level the server is providing is used.
Top Node Id The ID of the topnode under which all nodes should be imported. Please note, that you don’t need to import nodes if you would like to use them in your own script code. You can access in script any node the OPCUA server is importing.

The rest of the interface parameters does not need to be changed if your Server is accepting anonymous access.

Connection troubleshouting

If you have problems in connecting to your OPCUA server please follow these steps.

  1. Make your own test model. Copy the demo scene and use the configuration without security certificates. Please set server to the IP address of your OPC Server (e.g. opc.tcp://localhost:48010 if the server is running on the same machine):
  1. Use OpcWatch to check if you can reach the server from your machine. Download OpcWatch at this location:
    https://game4automation.com/download/OpcWatch.exe
    Start OpcWatch on the computer you are running Unity and put in the adress of your OPCUA server:

  2. Check with OpcWatch if it can connect to your OPC Server. Status of server should be shown as connected and you should be able to browse the sub nodes:

  3. If you are not able to browse the server check you server configuration. Your server should run with no security settings. No security certificates and passwords should be used for first tests.

  4. If you are still unable to browse the server, try to ping the server in a command line (e.g. ping 192.168.0.32). If there is no response from the ping you should check your firewall settings. Please turn the firewall on the server and your computer off.

  5. If you are able to browse the server get back to Unity. Check again, that in Unity the Server address in your model is the same as in your test with OpcWatch. Open the demo model and delete all sub nodes:

  6. Select node id you where able to browse with OpcWatch and put it into the field Top Node Id of the OPCUA_Interface configuration. Then press import nodes:

  7. You should now see the subnodes of your OPC UA server. In the Console you should see the message “Connected to OPC Client opc.tcp://192.168.0.32:48010 with Status Connected”

  8. Compile the application on your target device (Windows, Android, IOs) and test it.

  9. If your target device is not able to connect please check, if the build settings are set to .Net Standard 2.0 Compatibility level.

  10. If you are still not able to connect on your target device please use a tool to see the log file on your target device like for example https://assetstore.unity.com/packages/tools/gui/in-game-debug-console-68068

  11. Check the debug log on your mobile device. The log message should give you a hint about the problems on your mobile device.

Security Certificates

OPC UA is using certificates to ensure a secure communication. If you selected Auto Accept Server Certificates and Client Auto Generate Certificate a Client certificate will be automatically generated and the server certificate is automatically added to the trusted certificate folder.

You can define the sub folder (to the home folder) for the certificates with Certificate Path. Because Unity needs access to this folder the home folder is on IOS and Android the Application.persistentDataPath or on Windows the Application.streamingAssetsPath.

Generating your own Application certificate

For generating your own certificate you need to download the UA configuration tool of the OPC UA foundation. You can download it here: http://www.opclabs.com/products/ua-configuration-tool

After downloading you can generate your own certificate with this command line.

1
"C:\Program Files (x86)\UA Configuration Tool 1.03\Opc.Ua.CertificateGenerator.exe" -sp . -an game4automation

game4automation must be replaced with your application name and must be the same as the Application Name in the properties of the OPC UA interface.

This will generate you two folders, certs and private in the directory where you started *Opc.UA.CertificateGenerator.exe”. You need to copy these two folders into the StreamingAssetsPath.

To define your certificate you must enter the subpath (under the StreamingAssetsPath) of the .pfx file into the property Client Certificate Path:

Importing OPCUA Nodes

If the interface is configured and the server is accessible you can import the Nodes from the OPCUA server.

Push on Import Nodes and all nodes (under the Top Node ID) are imported and generated as Gameobjects with attached OPCUA_Node Scripts:

The OPCUA_Node Script is showing the Node information imported from the OPCUA server:

With the Button Update Node the data can be updated from the server.

If the Game4Automation framework is installed, additionally all corresponding PLCSignals are created. These signals can be dragged and dropped with sensors or drives of the Game4Automation framework.

When you now start the Simulation the OPCUA signals will be exchanged between Unity and the OPCUA Server.

OPCUA Nodes with Game4Automation PLCInputs and PLCOutputs

This section is only valid for customers who are using Game4Automation together with OPCUA4Unity. OPCUA4Unity is included in Game4Automation Professional.

The OPCUA interface uses in the source code several compile switches based on the Define Game4Automation to define a special behavior for Game4Automation. During signal import to all imported OPCUA nodes the corresponding PLCInputs and PLCOutput signals are added. PLCOutputs are automatically subscribed on the OPCUA server. PLCInputs should not be subscribed, because they are sent to the OPCUA server by Unity.

Because in most cases it is not possible to determine, if the OPCUA node should be a PLC input or a PLC output, the booleans Write Value, what means that the value is written to the OPCUA server and Read Value, what means that the value is read from the OPCUA server. Based on this and on the data type the corresponding PLCInput or PLCOutput script is added to the OPCUA node.

It is not possible to define an OPCUA node at the same time as PLCInput and PLCOutput. If you try to do that a warning message will be displayed in the log and no PLCInput or PLCOutput script will be added. If you want to use one node as input and output you need to code the interaction yourself (see below).

It is possible to define a RegEx in the OPCUA interface configuration to determine automatically which OPCUA symbols should be treated as Input or Output during signal import. One ore multiple Regex can be defined symbol names or parts of symbol names which should be treated as Write Signals - that means PLCInputs or outputs from Unity.

If you change anything on the above described Game4Automation related settings you can update all imported nodes by pushing on the button Update nodes

Using OPCUA Nodes

You find a full API class documentation online.

This section give you just an overview how to use OPCUA nodes based on the demo model.

Reading Values

For reading values you can use two methods.

Direct reading

First one (not recommended one) is to read directly from the OPCUA server with the commands

PLC_CanConveyor#
1
var myvar = Interface.ReadNodeValue ("ns=2;s=Demo.Dynamic.Scalar.UInt64")

You can find this methods on the OPCUA_Node Script as well as on the interface itself. If you have a direct reference to the Interface in your method you can do like this:

PLC_CanConveyor#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using UnityEditor;
using UnityEngine;
using game4automation;

public class DemoReadNodeNotRecommended : MonoBehaviour
{

public OPCUA_Interface Interface;
public string NodeId;

// Update is called once per frame
void Update()
{

float myvar = (float)Interface.ReadNodeValue(NodeId);
}
}

This method is not recommended because the read is not done multithreaded and this might block or slow your application.

Subscribing to node value changes

This is the recommended method. Here is an example:

PLC_CanConveyor#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using game4automation;
using UnityEngine;

public class DemoMoveCubeWithDelegate: MonoBehaviour
{
public OPCUA_Interface Interface;
public string NodeId;
public float PositionY;

private OPCUA_Node node;
private OPCUANodeSubscription subscription;

// Start is called before the first frame update
void Start()
{
if (Interface != null)
subscription = Interface.Subscribe(NodeId, NodeChanged); /// Subscribe to the nodeid with NodeChanged
}

public void NodeChanged(OPCUANodeSubscription sub, object obj) // Is called when Node Value of Node nodeid is changed
{
PositionY = (float) obj; // sets the new position based on the new value
}

// Update is called once per frame
void Update()
{
transform.rotation = Quaternion.Euler(new Vector3(0,PositionY,0));
}
}

Writing Values

Also for node writing there are two methods. One blocking one, which is not recommended, and one which is done in a parallel thread:

Direct writing

This is an example of direct writing (not recommended)

PLC_CanConveyor#
1
bool success = Interface.WriteNodeValue ("ns=2;s=Demo.Dynamic.Scalar.Float",100)

Writing by a parallel task which is watching the node

The recommended way for writing is to add a “WatchedNode” to the interface. With the Method AddWatchedNode you get a Node object back. This Node object will be watched automatically by a parallel task and each time the Value of the Node object is changing, the parallel task will update the server. This is non blocking because it happens in a total parallel task. See an example here:

PLC_CanConveyor#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using UnityEngine;
using game4automation;

public class DemoWriteNodeToServer : MonoBehaviour
{
public float Speed;
public OPCUA_Interface Interface;
public string NodeId;
public float Position;
private OPCUANode node;

// Start is called before the first frame update
void Start()
{
node = Interface.AddWatchedNode(NodeId); // Register node as watched node
}

// Update is called once per frame
void Update()
{
transform.Rotate(Vector3.left, Speed * Time.deltaTime);
Position = transform.rotation.eulerAngles.x; // Just for displaying it
node.Value = (int)transform.rotation.eulerAngles.x; // sets the new node value - because it is watched value will be automatically transfered to OPC Server
}
}

For more information please check the online API class documentation documentation.

Calling OPCUA Methods

To call methods you can use CallMethod.

Note that first the NodeId of the owner of the method has to be given and
then the NodeID MethodID of the method itself. CallMethod allows to pass multiple parameters to the called method. CallMethod returns the results in an object array.

DemoCallMethod#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

using game4automation;
using UnityEngine;

public class DemoCallMethod : MonoBehaviour
{
public OPCUA_Interface Interface;
public string NodeId;
public string MethodId;
public double MethodParameterA;
public double MethodParameterB;
public double Result;
private double _a, _b;

void Update()
{
// if parameter changed
if (_a != MethodParameterA || _b != MethodParameterB)
{
var res = Interface.CallMethod(NodeId, MethodId,MethodParameterA,MethodParameterB); // calls a method with NodeID MethodID in Node NodeId with Parameters MethodParameterA and MethodParameterB
Result = (double) res[0]; // The result is returned as an object array
}
_a = MethodParameterA;
_b = MethodParameterB;
}
}





© 2019 in2Sight GmbH https://game4automation.com - All rights reserved. No part of this publication may be reproduced, distributed, or transmitted in any form or by any means, including printing, saving, photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the publisher.