.NET 환경에서 OPC UA 프로토콜 구현 및 데이터 통신 가이드

OPC UA 개요

OPC UA(OPC Unified Architecture)는 산업 자동화 분야에서 기기 간 데이터 교환을 위해 설계된 독립형 플랫폼 통신 프로토콜입니다. 기존의 Windows 종속적인 OPC DA와 달리, OPC UA는 리눅스, macOS, Windows 등 다양한 운영체제에서 동작하며 현대적인 보안 모델과 유연한 정보 모델을 제공합니다.

OPC UA의 핵심은 주소 공간(Address Space) 내의 노드(Node) 구조입니다. 각 노드는 객체, 변수, 메서드 등으로 정의되며 참조(Reference)를 통해 서로 연결됩니다. 이러한 객체 지향적 접근 방식을 통해 복잡한 산업 기기의 데이터를 체계적으로 관리할 수 있으며, 인증, 암호화, 메시지 서명 등의 강력한 보안 기능을 기본적으로 포함하고 있습니다.

UaExpert를 활용한 서버 연결 테스트

UaExpert는 OPC UA 서버와의 통신을 검증하기 위한 대표적인 클라이언트 소프트웨어입니다. 서버의 노드 구조를 시각적으로 확인하고 데이터 변화를 모니터링하는 데 필수적입니다.

  • 서버 등록: 메뉴의 [Server] - [Add]를 선택하여 접속하려는 서버의 엔드포인트 URL(예: opc.tcp://localhost:4840)을 입력합니다.
  • 연결 설정: 등록된 서버를 마우스 오른쪽 버튼으로 클릭하고 [Connect]를 선택하여 세션을 활성화합니다. 최초 연결 시 서버 인증서를 신뢰할 것인지 묻는 팝업이 나타날 수 있습니다.
  • 데이터 모니터링: 'Address Space' 탭에서 PLC나 서버의 노드를 찾아 'Data Access View'로 드래그하면 실시간으로 값이 업데이트되는 것을 확인할 수 있습니다.

C#을 이용한 OPC UA 통신 구현

.NET 프로젝트에서 OPC UA를 구현하기 위해서는 OPCFoundation.NetStandard.Opc.Ua NuGet 패키지를 설치해야 합니다.

1. 클라이언트 구성 및 세션 생성

애플리케이션의 보안 설정 및 인증서 관리를 위한 구성을 정의하고 서버와의 세션을 구축합니다.

// 클라이언트 애플리케이션 설정 정의
var appConfig = new ApplicationConfiguration()
{
    ApplicationName = "DotNetOpcUaClient",
    ApplicationUri = Utils.Format(@"urn:{0}:DotNetOpcUaClient", System.Net.Dns.GetHostName()),
    ApplicationType = ApplicationType.Client,
    SecurityConfiguration = new SecurityConfiguration
    {
        ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "OpcUaClient" },
        AutoAcceptUntrustedCertificates = true, // 테스트 환경용 설정
        RejectSHA1SignedCertificates = false,
        MinimumCertificateKeySize = 2048
    },
    TransportQuotas = new TransportQuotas { OperationTimeout = 20000 },
    ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
};

await appConfig.Validate(ApplicationType.Client);

// 인증서 유효성 검사 이벤트 핸들러
appConfig.CertificateValidator.CertificateValidation += (sender, args) => 
{
    args.Accept = (args.Error.StatusCode == StatusCodes.BadCertificateUntrusted);
};

// 엔드포인트 선택 및 세션 시작
var serverUrl = "opc.tcp://127.0.0.1:4840";
var endpointDesc = CoreClientUtils.SelectEndpoint(serverUrl, useSecurity: true);
var endpointConfig = EndpointConfiguration.Create(appConfig);
var remoteEndpoint = new ConfiguredEndpoint(null, endpointDesc, endpointConfig);

var uaSession = await Session.Create(appConfig, remoteEndpoint, false, "SessionName", 60000, new UserIdentity(new AnonymousIdentityToken()), null);

2. 노드 데이터 읽기 및 쓰기

특정 노드 식별자(NodeId)를 사용하여 데이터를 조회하거나 변경할 수 있습니다.

// 동기 방식으로 단일 노드 읽기
string targetNodeId = "ns=2;s=TemperatureSensor";
DataValue result = uaSession.ReadValue(targetNodeId);
Console.WriteLine($"값: {result.Value}, 상태: {result.StatusCode}, 시간: {result.SourceTimestamp}");

// 노드 데이터 쓰기
var newValue = new WriteValue()
{
    NodeId = targetNodeId,
    Value = new DataValue(new Variant(25.5f)) // float 타입 데이터 쓰기
};

StatusCodeCollection results;
DiagnosticInfoCollection diagInfos;
uaSession.Write(null, new WriteValueCollection { newValue }, out results, out diagInfos);

if (StatusCode.IsGood(results[0]))
{
    Console.WriteLine("데이터 쓰기 성공");
}

3. 데이터 구독(Subscription) 설정

데이터가 변경될 때마다 이벤트를 수신하도록 구독 기능을 설정합니다.

// 구독 객체 생성 (게시 간격 500ms)
var monitorGroup = new Subscription(uaSession.DefaultSubscription) { PublishingInterval = 500 };
uaSession.AddSubscription(monitorGroup);
monitorGroup.Create();

// 감시 항목 정의
var itemToMonitor = new MonitoredItem(monitorGroup.DefaultItem)
{
    DisplayName = "CurrentValue",
    StartNodeId = "ns=2;s=ProcessVariable"
};

// 데이터 변경 알림 핸들러 등록
itemToMonitor.Notification += (item, e) =>
{
    foreach (var val in item.DequeueValues())
    {
        Console.WriteLine($"변동 감지 - 노드: {item.DisplayName}, 새로운 값: {val.Value}");
    }
};

monitorGroup.AddItem(itemToMonitor);
monitorGroup.ApplyChanges();

태그: OPC-UA .NET C# Industrial-IoT UaExpert

9월 6일 14:06에 게시됨