108 lines
4.5 KiB
C#
108 lines
4.5 KiB
C#
using Opc.Ua;
|
|
using Opc.Ua.Client;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using OpcPks.Core.Models;
|
|
|
|
namespace OpcPks.Core.Services
|
|
{
|
|
public class OpcSessionManager
|
|
{
|
|
private readonly string _pkiPath = "/home/pacer/projects/OpcPksPlatform/OpcPks.Core/Data/pki";
|
|
|
|
/// <summary>
|
|
/// [수정] 하니웰 인사용: 단순히 연결만 하는 게 아니라 서버 시간을 읽으려 시도하여
|
|
/// 하니웰 본체 엔진이 인증서를 Rejected로 던지도록 유도합니다.
|
|
/// </summary>
|
|
public async Task<bool> SayHelloAsync(string ip)
|
|
{
|
|
try
|
|
{
|
|
// CertRequestModel은 최소 정보만 담아 전달
|
|
using (var session = await GetSessionAsync(ip, new CertRequestModel { PrimaryIpA = ip }))
|
|
{
|
|
if (session != null && session.Connected)
|
|
{
|
|
// 연결 성공 시 서버 시간 노드를 읽어 실제 통신이 가능한지 확인
|
|
var currentTime = session.ReadValue(Variables.Server_ServerStatus_CurrentTime);
|
|
Console.WriteLine($"✅ [SayHello] 하니웰 연결 및 데이터 읽기 성공: {currentTime}");
|
|
|
|
await session.CloseAsync();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 여기서 에러가 나야 정상입니다. (인증서가 신뢰되지 않았을 때 하니웰이 거부하며 파일을 Rejected로 보냄)
|
|
Console.WriteLine($"⚠️ [SayHello] 하니웰 거부 반응 유도 성공: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// [핵심] 크롤러 및 모든 서비스가 공통으로 사용하는 실제 세션 생성 로직
|
|
/// </summary>
|
|
public async Task<ISession?> GetSessionAsync(string ip, CertRequestModel model)
|
|
{
|
|
if (string.IsNullOrEmpty(ip)) return null;
|
|
|
|
string endpointUrl = $"opc.tcp://{ip}:4840";
|
|
|
|
var config = new ApplicationConfiguration()
|
|
{
|
|
ApplicationName = "OpcPksClient",
|
|
ApplicationType = ApplicationType.Client,
|
|
SecurityConfiguration = new SecurityConfiguration
|
|
{
|
|
ApplicationCertificate = new CertificateIdentifier {
|
|
StoreType = "Directory",
|
|
StorePath = $"{_pkiPath}/own"
|
|
},
|
|
TrustedPeerCertificates = new CertificateTrustList {
|
|
StoreType = "Directory",
|
|
StorePath = $"{_pkiPath}/trusted"
|
|
},
|
|
RejectedCertificateStore = new CertificateTrustList {
|
|
StoreType = "Directory",
|
|
StorePath = $"{_pkiPath}/rejected"
|
|
},
|
|
AutoAcceptUntrustedCertificates = true
|
|
},
|
|
TransportQuotas = new TransportQuotas { OperationTimeout = 10000 },
|
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 10000 }
|
|
};
|
|
|
|
await config.Validate(ApplicationType.Client);
|
|
|
|
try
|
|
{
|
|
// 하니웰 보안 설정에 맞는 엔드포인트 선택
|
|
var endpointDescription = CoreClientUtils.SelectEndpoint(endpointUrl, true, 5000);
|
|
var endpointConfiguration = EndpointConfiguration.Create(config);
|
|
var endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
|
|
|
|
// 세션 생성 시도: 이 과정 자체가 하니웰 본체에 대한 보안 컨택입니다.
|
|
return await Session.Create(
|
|
config,
|
|
endpoint,
|
|
false,
|
|
"OpcPksSession",
|
|
10000,
|
|
new UserIdentity(new AnonymousIdentityToken()),
|
|
null);
|
|
}
|
|
catch (ServiceResultException sx)
|
|
{
|
|
Console.WriteLine($"[OPC_UA] 하니웰 보안 응답 코드: {sx.StatusCode}");
|
|
return null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[OPC_UA] 세션 생성 중 오류: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
} |