Skip to content

Latest commit

 

History

History
417 lines (338 loc) · 13.3 KB

File metadata and controls

417 lines (338 loc) · 13.3 KB

GodSharp.Opc.Ua

Azure DevOps builds (main)

Package Version

Name NuGet MyGet
GodSharp.Opc.Ua.Common NuGet MyGet
GodSharp.Opc.Ua.Client NuGet MyGet
GodSharp.Opc.Ua.ProxyServer NuGet MyGet
GodSharp.Opc.Ua.Server NuGet MyGet
GodSharp.Opc.Ua.Server.AspNetCore NuGet MyGet
GodSharp.Opc.Ua.ComplexTypes NuGet MyGet

Introduction

Package Uasge
GodSharp.Opc.Ua.Common a opc ua common lib
GodSharp.Opc.Ua.Client a opc ua client
GodSharp.Opc.Ua.ProxyServer a proxy for opc ua server
GodSharp.Opc.Ua.Server a opc ua server
GodSharp.Opc.Ua.Server.AspNetCore opc ua server for asp.net core
GodSharp.Opc.Ua.ComplexTypes custom generate encode/decode method for EncodeableObject class

Getting Started

PM> Install-Package GodSharp.Opc.Ua.Client

Discovery Server

Sample code:

var url = "opc.tcp://127.0.0.1:4840";
OpcUaServerDiscovery discovery = new OpcUaServerDiscovery();

Console.WriteLine("discovery Discovery");
var servers = discovery.Discovery(url);
foreach (var item in servers)
{
    foreach (var durl in item.DiscoveryUrls)
    {
        Console.WriteLine($"{durl}");
        var endpoints = discovery.GetEndpoints(durl);
        if (endpoints == null) continue;
        foreach (var endpoint in endpoints)
        {
            Console.WriteLine($"\t- {endpoint.EndpointUrl}/ {endpoint.SecurityMode}/  {endpoint.SecurityPolicyUri}");
        }
    }
}

Console.WriteLine("discovery DiscoveryUrls");
var discoverys = discovery.DiscoveryUrls(url);
if (discoverys != null)
{
    foreach (var discoveryUrl in discoverys)
    {
        Console.WriteLine($"{discoveryUrl}");
        var endpoints = discovery.GetEndpoints(discoveryUrl);
        if (endpoints == null) continue;
        foreach (var endpoint in endpoints)
        {
            Console.WriteLine($"\t- {endpoint.EndpointUrl}/ {endpoint.SecurityMode}/  {endpoint.SecurityPolicyUri}");
        }
    }
}

Console.WriteLine("discovery finished");

Initial : Create opc ua client

Sample code:

OpcUaClientBuider buider = new OpcUaClientBuider();

//var cert = new X509Certificate2(@".\.opc\cert\godsharpopcuacert.der", "123456",  X509KeyStorageFlags.MachineKeySet |   X509KeyStorageFlags.Exportable);

//var cert2 = CertificateFactory.CreateCertificateWithPEMPrivateKey(cert, File.ReadAllBytes(@".\.opc\cert\godsharpopcuacert_key.pem"));

buider
    .WithEndpoint(url)
    .WithAnonymous()
    //.WithAccount("root","secret")
    //.WithAccount("root","secret12345678")
    //.WithCertificate(cert2)
    //.WithSecurity  (MessageSecurityMode.SignAndEncrypt,SecurityPolicies.Ba s ic256Sha256)
    .WithClientId("GodSharpOpcUaClientConsole");

var client = buider.Build();
{
    client.OnSessionConnectNotification = (s, t) =>
    {
        switch (t)
        {
            case ClientSessionConnectionState.Connected:
                Console.WriteLine  ($"[{DateTime.Now:HH:mm:ss.fff}]  {s.SessionName}:connected");
                break;
            case ClientSessionConnectionState.Reconnecting:
                Console.WriteLine  ($"[{DateTime.Now:HH:mm:ss.fff}]  {s.SessionName}:reconnecting");
                break;
            case ClientSessionConnectionState.Disconnecting:
                Console.WriteLine  ($"[{DateTime.Now:HH:mm:ss.fff}]  {s.SessionName}:disconnecting");
                break;
            case ClientSessionConnectionState.Disconnected:
                Console.WriteLine  ($"[{DateTime.Now:HH:mm:ss.fff}]  {s.SessionName}:disconnected");
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof  (t), t, null);
        }
    };
    client.OnSessionKeepAlive = (s, e) =>
    {
        //Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}]  {s.SessionName}:{e.CurrentState}");
    };
    client.OnSessionSubscriptionChanged = subscription =>
    {
        foreach (var item in subscription.Notifications)
        {
            //Console.WriteLine  ($"[{DateTime.Now:HH:mm:ss.fff}]  {item..SessionName}:{e.CurrentState}");
        }
    };
    client.OnMonitoredItemNotification = (n, i, e) =>
    {
        foreach (var value in i.DequeueValues())
        {
            Console.WriteLine("{0}->{1} : {2}, {3}, {4}", n,   i.DisplayName, value.Value,   value.SourceTimestamp, value.StatusCode);
        }
    };
}

Connect to Opc Server

Sample code:

Console.WriteLine("1 - StartAsync ...");
bool ret = await client.StartAsync();
Console.WriteLine($"connect {ret}");

Browse / BrowseTree

  • Browse: To browse node list with specialized node or default.

  • BrowseTree: To browse node tree with specialized node or default.

    Sample code:

    // To browse node list with specialized node or default 
    var all = client.Session.Browse();
    //var browse = client.Session.Browse(new NodeId  ("ns=4;s=Demo.Static"));
    Console.WriteLine(" DisplayName, BrowseName, NodeClass");
    foreach (var obj in all)
    {
        Console.WriteLine(" {0}, {1}, {2}", obj.DisplayName,   obj.BrowseName, obj.NodeClass);
    
        var browse2 = client.Session.Browse((NodeId)obj.NodeId);
        foreach (var refd in browse2)
        {
            Console.WriteLine("   + {0}, {1}, {2}",   refd.DisplayName, refd.BrowseName, refd.NodeClass);
        }
    }
    
    // To browse node tree with specialized node or default
    var tree = client.Session.BrowseTree();
    //var tree = client.Session.BrowseTree(new NodeId  ("ns=4;s=Demo.Static"));
    Browse(tree);
    
    static void Browse(IEnumerable<ReferenceBrowseDescription>   refs, int level = -1)
    {
        level++;
        foreach (var description in refs)
        {
            Console.WriteLine("{0}+{1}, {2},{3}",
                new string('\t', level),
                //Formatter.FormatAttributeValue  (attribute.ValueId.AttributeId,   attribute.Value)}
                //description.Node.BrowseName, 
                description.GetFormatText(),
                description.Node.NodeClass,
                description.Node.NodeId
            );
            if (description.Children != null)
            {
                Browse(description.Children, level);
            }
        }
    }

GetAttributes / GetProperties

Sample code:

var node = new NodeId("ns=0;i=2258"); // 2258   Server.ServerStatus.CurrentTime
var attributes = client.Session.GetAttributes(node);
foreach (var attribute in attributes)
{
    Console.WriteLine($"{attribute.Name}:  {attribute.ValueText}");
}

var properties = client.Session.GetProperties(node);
if (properties != null)
{
    foreach (var attribute in properties)
    {
        Console.WriteLine($"{attribute.Name}:  {Formatter.FormatAttributeValue  (attribute.ValueId.AttributeId, attribute.Value,   client.Session)}");
    }
}

Subscribe / Unsubscribe

Sample code:

var sub_name = "andon";
var subscribes = new string[] { "ns=0;i=2258",   "ns=0;i=2259" };
// 2258 Server.ServerStatus.CurrentTime
// 2259 Server.ServerStatus.State

client.Subscribe(sub_name, subscribes);

Console.WriteLine("Press any key to Unsubscribe");
Console.ReadLine();

client.Unsubscribe(sub_name);

Read Node

Sample code:

T val = client.Session.Read<T>(node);
// or
DataValue val = client.Session.Read(node);

Write Node

Sample code:

var ret = client.Session.Write(node, value);

Disconnect to Opc Server

Sample code:

var ret = await client.StopAsync();

MsBuild

Generate code for which class is customized with ComplexObjectGenerator attribute, the class generated is implement ComplexObject.

PM> Install-Package GodSharp.Extensions.Opc.Ua.Generator
PM> Install-Package GodSharp.Extensions.Opc.Ua.MsBuild

ComplexObject class types:

[DefaultValue(ComplexObjectType.EncodeableObject)]
public enum ComplexObjectType
{
    EncodeableObject,
    SwitchField,
    OptionalField
}

Sample code:

[ComplexObjectGenerator(ComplexObjectType.SwitchField,   EncodingMethodType.Factory)]
public partial class UaAnsiUnion
{
    [SwitchField(1)]
    public int Int32;
    [SwitchField(2, 4)]
    public string String;

    public UaAnsiUnion()
    {
        TypeIdNamespace = "nsu=http://www.unifiedautomation.com/DemoServer/;i=3006";
        BinaryEncodingIdNamespace = "nsu=http://www.unifiedautomation.com/DemoServer/;i=5003";
    }
}

Just build project, code will be generated by msbuild task in the file with extension {filename}.uamgen.cs by default.

like this:

//----------------------------------------------------------- - ------------------
// <auto-generated>
//     Generated by MSBuild generator.
//     Source: UaAnsiUnion.cs
// </auto-generated>
//----------------------------------------------------------- - ------------------

using GodSharp.Extensions.Opc.Ua.Types;
using Opc.Ua;
using static   GodSharp.Extensions.Opc.Ua.Types.Encodings.EncodingFactory;

namespace GodSharpOpcUaClientSample.Types
{
	public partial class UaAnsiUnion : ComplexObject 
	{
		public uint SwitchField;

		public override void Encode(IEncoder encoder)
		{
			base.Encode(encoder);
			encoder.WriteUInt32("SwitchField",SwitchField);
			switch (SwitchField)
			{
				case 1:
					Encoding.Write(encoder, Int32, nameof  (Int32));
					break;
				case 2:
				case 4:
					Encoding.Write(encoder, String, nameof  (String));
					break;
				default:
					break;
			}
		}

		public override void Decode(IDecoder decoder)
		{
			base.Decode(decoder);
			SwitchField = decoder.ReadUInt32("SwitchField");
			switch (SwitchField)
			{
				case 1:
					Encoding.Read(decoder,ref Int32, nameof  (Int32));
					break;
				case 2:
				case 4:
					Encoding.Read(decoder,ref String, nameof  (String));
					break;
				default:
					break;
			}
		}
	}
}

Register Custom Types

Register Custom Type Namespace

You can register custom type namespace by hard code in constructor.

Sample code:

[ComplexObjectGenerator(ComplexObjectType.SwitchField,   EncodingMethodType.Factory)]
public partial class UaAnsiUnion
{
    [SwitchField(1)]
    public int Int32;
    [SwitchField(2, 4)]
    public string String;

    public UaAnsiUnion()
    {
        TypeIdNamespace = "nsu=http://  www.unifiedautomation.com/DemoServer/;i=3006";
        BinaryEncodingIdNamespace = "nsu=http://  www.unifiedautomation.com/DemoServer/;i=5003";
    }
}

Also can support by configuration from file or db,and others.

Sample code:

EncodingFactory.Instance.RegisterTypeNamespace(
new TypeNamespace()
{
    Type = typeof(UaAnsiVector).AssemblyQualifiedName,
    TypeId = "nsu=http://www.unifiedautomation.com/  DemoServer/;i=3002",
    BinaryEncodingId = "nsu=http://www.unifiedautomation.com/  DemoServer/;i=5054"
}
);

Register Custom Type to System

Sample code:

EncodingFactory.Instance.RegisterEncodeableTypes(typeof(UaAnsiVector), typeof(UaAnsiVector));
EncodingFactory.Instance.RegisterEncodeableTypes(Assembly.GetEntryAssembly(),Assembly.GetExecutingAssembly());

License

Free!