IT’s Ha

[OPC] 4. C#을 통한 OPC UA Client 개발 본문

OPC

[OPC] 4. C#을 통한 OPC UA Client 개발

Deleloper Ha 2023. 3. 30. 15:18
728x90
반응형

안녕하세요. 이번 포스팅은 OPC UA Client를 개발 포스팅을 진행하겠습니다. 

이번 포스팅의 개발 환경은 C#을 통하여 개발하였고, .NET 7.0 그리고 Winform에서 구현하였습니다. 그리고 이전 포스팅에 대한 내용이 이어서 KepServer에 연결하여 테스트 하겠습니다. 

2023.03.15 - [OPC] - [OPC] 3. OPC UA와 PLC 통신 예제

 

[OPC] 3. OPC UA와 PLC 통신 예제

안녕하세요. 지난시간에 이어 오늘은 상용 OPC UA서버와 PLC간의 연결을 하려고합니다. 오늘 사용 될 프로그램은 모두 상용프로그램으로 구매시 비용이 발생됩니다. 사용 될 서버는 KEPServerEX와 클

oppr123.tistory.com

1. 프로젝트 생성 

프로젝트 Winform으로 생성을 해주세요. 그리고 프로젝트 우클릭 후 Nuget패키지에서 OPCFoundation에서 제공하는 OPC.UA와 OPC.UA.Client를 설치 해주세요.

Nuget 패키지 설치 항목

2.  화면 구성

디자인 파일에는 ListView를 넣어 LogTime과 Message 항목을 추가 하였습니다. 

화면 구성

3. 소스 구현

이번 소스 예제는 Security를 제외하고 구현하였습니다. User 체크 그리고 인증서 체크가 없이 간단한 Client 프로그램을 작성하였습니다. 

public partial class Form1 : Form
{
    private Subscription _subscription;
    public Form1()
    {
        InitializeComponent();
    }
    private async void Connect()
    {
        try
        {
            //연결 Url 설정 (KepServer - Ua Configration 에서 확인 가능)
            string endpointUrl = "opc.tcp://localhost:49320";
            
            //OPC UA Client 설정 시작
            Opc.Ua.ApplicationConfiguration config = new Opc.Ua.ApplicationConfiguration()
            {
                ApplicationName = "OPCClientTest",
                ApplicationUri = Utils.Format(@"urn:{0}:OPCClientTest", System.Net.Dns.GetHostName()),
                ApplicationType = ApplicationType.Client,
                SecurityConfiguration = new SecurityConfiguration
                {
                        ApplicationCertificate = new CertificateIdentifier(),
                        TrustedPeerCertificates = new CertificateTrustList (),
                        RejectedCertificateStore = new CertificateStoreIdentifier(),
                        AutoAcceptUntrustedCertificates = true,
                        RejectSHA1SignedCertificates = false
                },
                TransportConfigurations = new TransportConfigurationCollection(),
                TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
                ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
                TraceConfiguration = new TraceConfiguration(),
            }
            
            //연결 시작(Session 연결)
            var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl, useSecurity: false);
            var endconf = new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config));
            var session = Session.Create(config, endconf, true, "session", 1000, null, null).GetAwaiter().GetResult();
            
            //모니터링 설정
            _subscription = new Subscription(session.DefaultSubscription)
            {
                PublishingEnabled = true,
                PublishingInterval = 500,
            };
            
            // 모니터링 할 Item List
            var list = new List<MonitoredItem> { };
            
            // List 추가
            list.Add(new MonitoredItem()
            {
                DisplayName = "Tag1",
                StartNodeId = "ns=2;s=Channel.Device1.Tag1"
            });
            list.Add(new MonitoredItem()
            {
                DisplayName = "Tag2",
                StartNodeId = "ns=2;s=Channel.Device1.Tag2"
            });
            list.Add(new MonitoredItem()
            {
                DisplayName = "Tag3",
                StartNodeId = "ns=2;s=Channel.Device1.Tag3"
            });
            
            //각각의 Item에 Event추가
            list.ForEach(i => i.Notification += new MonitoredItemNotificationEventHandler(OnNotification));
            
            //Subscription에 List 추가
            _subscription.AddItems(list);
            
            //Session에 Subscription 추가
            session.AddSubscription(_subscription);
            
            //Subscription 생성
            _subscription.Create();
        }
        catch(Exception ex)
        {
        
        }
    }
    
    //모니터링
    private void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
    {
        try
        {
            MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;

            foreach (var value in item.DequeueValues())
            {
                this.Invoke(new MethodInvoker(delegate ()
                {
                    //상태가 정상 일 경우
                    if (StatusCode.IsGood(value.StatusCode))
                    {
                        if (EventList.Items.Count > 100)
                            EventList.Items.RemoveAt(EventList.Items.Count - 1);
                        EventList.Items.Insert(0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        EventList.Items[0].SubItems.Add("[Value] : " + value.Value.ToString() + ", ID:" + item.DisplayName);
                    }
                    //상태가 정상 아닐 경우
                    else
                    {
                        if (EventList.Items.Count > 100)
                            EventList.Items.RemoveAt(EventList.Items.Count - 1);
                        EventList.Items.Insert(0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        EventList.Items[0].SubItems.Add("[STATUS] : " + value.StatusCode.ToString() + ", ID:" + item.DisplayName);
                    }
                }));
            }
        }
        catch (Exception ex)
        {}
    }
    //Form Load 이벤트 추가
    private void Form1_Load(object sender, EventArgs e)
    {
        Connect();
    }
}

4. 결과

결과

정상적으로 값을 받아오는 것을 확인 할 수 있습니다. 위는 Winform의 예제이지만 C#으로 구성되어있는 WFP나 ASP.NET등에서도 쉽게 적용이 가능합니다. 궁금하신 점이나 잘못된 점은 메일 또는 댓글에 남겨 주시면 수정 또는 답변 드리도록 하겠습니다. 감사합니다.

※ 2024-02-15 OnNotification 함수 문제로 수정
 - private void OnNotification(onitoredItem item, MonitoredItemNotificationEventArgs e) ->
   private void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)

728x90
반응형

'OPC' 카테고리의 다른 글

[OPC] 5. C#을 통한 OPC UA Client 개발 - Write  (1) 2024.02.15
[OPC] 3. OPC UA와 PLC 통신 예제  (7) 2023.03.15
[OPC] 2. OPC UA와 OPC DA의 차이, PLC와 OPC통신  (0) 2023.03.15
[OPC] 1. OPC UA 서버의 이해  (0) 2023.03.08
[OPC]OPC  (0) 2023.02.15
Comments