TAG 1 개 읽기 성공!
This commit is contained in:
55
.Notebook/Configuration 파일 생성.md
Normal file
55
.Notebook/Configuration 파일 생성.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
cat > OpcTestClient.Config.xml << 'EOF'
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ApplicationConfiguration
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd"
|
||||||
|
xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd">
|
||||||
|
|
||||||
|
<ApplicationName>OPC Test Client</ApplicationName>
|
||||||
|
<ApplicationUri>urn:localhost:OpcTestClient</ApplicationUri>
|
||||||
|
<ApplicationType>Client_1</ApplicationType>
|
||||||
|
|
||||||
|
<SecurityConfiguration>
|
||||||
|
<ApplicationCertificate>
|
||||||
|
<StoreType>Directory</StoreType>
|
||||||
|
<StorePath>%CommonApplicationData%/OPC Foundation/pki/own</StorePath>
|
||||||
|
<SubjectName>CN=OPC Test Client</SubjectName>
|
||||||
|
</ApplicationCertificate>
|
||||||
|
|
||||||
|
<TrustedPeerCertificates>
|
||||||
|
<StoreType>Directory</StoreType>
|
||||||
|
<StorePath>%CommonApplicationData%/OPC Foundation/pki/trusted</StorePath>
|
||||||
|
</TrustedPeerCertificates>
|
||||||
|
|
||||||
|
<RejectedCertificateStore>
|
||||||
|
<StoreType>Directory</StoreType>
|
||||||
|
<StorePath>%CommonApplicationData%/OPC Foundation/pki/rejected</StorePath>
|
||||||
|
</RejectedCertificateStore>
|
||||||
|
|
||||||
|
<AutoAcceptUntrustedCertificates>true</AutoAcceptUntrustedCertificates>
|
||||||
|
</SecurityConfiguration>
|
||||||
|
|
||||||
|
<TransportQuotas>
|
||||||
|
<OperationTimeout>600000</OperationTimeout>
|
||||||
|
<MaxStringLength>1048576</MaxStringLength>
|
||||||
|
<MaxByteStringLength>1048576</MaxByteStringLength>
|
||||||
|
<MaxArrayLength>65536</MaxArrayLength>
|
||||||
|
<MaxMessageSize>4194304</MaxMessageSize>
|
||||||
|
<MaxBufferSize>65536</MaxBufferSize>
|
||||||
|
<ChannelLifetime>300000</ChannelLifetime>
|
||||||
|
<SecurityTokenLifetime>3600000</SecurityTokenLifetime>
|
||||||
|
</TransportQuotas>
|
||||||
|
|
||||||
|
<ClientConfiguration>
|
||||||
|
<DefaultSessionTimeout>60000</DefaultSessionTimeout>
|
||||||
|
<MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
|
||||||
|
</ClientConfiguration>
|
||||||
|
|
||||||
|
<TraceConfiguration>
|
||||||
|
<OutputFilePath>OpcTest.log</OutputFilePath>
|
||||||
|
<DeleteOnLoad>true</DeleteOnLoad>
|
||||||
|
</TraceConfiguration>
|
||||||
|
</ApplicationConfiguration>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "✅ Config file created!"
|
||||||
24
OpcConnectionTest/OpcConnectionTest.sln
Normal file
24
OpcConnectionTest/OpcConnectionTest.sln
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpcConnectionTest", "OpcConnectionTest.csproj", "{C5537E83-BE41-3CD8-A6DF-DAE381FC5D5C}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C5537E83-BE41-3CD8-A6DF-DAE381FC5D5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C5537E83-BE41-3CD8-A6DF-DAE381FC5D5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C5537E83-BE41-3CD8-A6DF-DAE381FC5D5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C5537E83-BE41-3CD8-A6DF-DAE381FC5D5C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {382A4C92-79E5-4684-B03A-688BC4DC21D3}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
358
OpcConnectionTest/Program copy.cs.no1
Normal file
358
OpcConnectionTest/Program copy.cs.no1
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
public class StatusCodeInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Hex { get; set; } = "";
|
||||||
|
public ulong Decimal { get; set; }
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
[Obsolete]
|
||||||
|
|
||||||
|
static Dictionary<uint, StatusCodeInfo> _statusCodeMap = new();
|
||||||
|
|
||||||
|
static void LoadStatusCodes()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string path = Path.Combine(Directory.GetCurrentDirectory(), "statuscode.json");
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Console.WriteLine("⚠️ statuscode.json 파일을 찾을 수 없습니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
var list = JsonSerializer.Deserialize<List<StatusCodeInfo>>(json);
|
||||||
|
|
||||||
|
if (list != null)
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
_statusCodeMap[(uint)item.Decimal] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ StatusCode { _statusCodeMap.Count }개 로드 완료\n");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ statuscode.json 로드 실패: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
|
||||||
|
LoadStatusCodes();
|
||||||
|
|
||||||
|
|
||||||
|
// ⚠️ Experion 서버 IP 주소 수정
|
||||||
|
string endpoint = "opc.tcp://192.168.0.20:4840";
|
||||||
|
|
||||||
|
// ⚠️ Honeywell CA로 서명된 클라이언트 인증서 경로 및 비밀번호
|
||||||
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
|
string pfxPassword = ""; // ⚠️ PFX 비밀번호 (없으면 빈 문자열)
|
||||||
|
|
||||||
|
// ⚠️ Experion Windows 계정 정보
|
||||||
|
string userName = "mngr"; // 예: "DOMAIN\\user" 또는 "localuser"
|
||||||
|
string password = "mngr";
|
||||||
|
|
||||||
|
Console.WriteLine($"Server: {endpoint}");
|
||||||
|
Console.WriteLine($"User: {userName}\n");
|
||||||
|
|
||||||
|
// PFX 파일 존재 여부 확인
|
||||||
|
if (!File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ PFX 파일을 찾을 수 없습니다: {pfxPath}");
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Honeywell CA 서명 인증서 로드
|
||||||
|
// Exportable: OPC UA 채널 서명 시 개인키 접근 필요
|
||||||
|
X509Certificate2 clientCertificate = new X509Certificate2(
|
||||||
|
pfxPath,
|
||||||
|
pfxPassword,
|
||||||
|
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ 인증서 로드: {clientCertificate.Subject}");
|
||||||
|
Console.WriteLine($" 유효기간: {clientCertificate.NotBefore:yyyy-MM-dd} ~ {clientCertificate.NotAfter:yyyy-MM-dd}");
|
||||||
|
Console.WriteLine($" 개인키 포함: {clientCertificate.HasPrivateKey}\n");
|
||||||
|
|
||||||
|
if (!clientCertificate.HasPrivateKey)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ 개인키가 없습니다. PFX 파일을 확인하세요.");
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. Configuration 생성
|
||||||
|
var config = new ApplicationConfiguration()
|
||||||
|
{
|
||||||
|
ApplicationName = "OPC Test Client",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = "urn:OpcTestClient",
|
||||||
|
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/own"),
|
||||||
|
SubjectName = clientCertificate.Subject,
|
||||||
|
// Honeywell CA 서명 인증서를 직접 주입
|
||||||
|
Certificate = clientCertificate
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/trusted")
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
// ⚠️ Honeywell 내부 CA 인증서를 이 폴더에 배치해야 합니다
|
||||||
|
// Experion Station에서 CA 인증서를 내보내어 pki/issuers/certs/ 에 복사
|
||||||
|
StorePath = Path.GetFullPath("pki/issuers")
|
||||||
|
},
|
||||||
|
|
||||||
|
RejectedCertificateStore = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/rejected")
|
||||||
|
},
|
||||||
|
|
||||||
|
// Honeywell CA 서명 인증서이므로 자동 수락 불필요 — false 권장
|
||||||
|
// 테스트 중 서버 인증서 검증 실패 시 true로 임시 변경 가능
|
||||||
|
AutoAcceptUntrustedCertificates = false,
|
||||||
|
RejectSHA1SignedCertificates = false,
|
||||||
|
AddAppCertToTrustedStore = false
|
||||||
|
},
|
||||||
|
|
||||||
|
TransportConfigurations = new TransportConfigurationCollection(),
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 서버 인증서 검증 실패 시 로그만 출력하는 핸들러
|
||||||
|
// Honeywell CA를 pki/issuers/에 제대로 넣으면 이 핸들러까지 오지 않아야 정상
|
||||||
|
// 불가피한 경우 e.Accept = true; 주석 해제 (운영 환경에서는 사용 금지)
|
||||||
|
config.CertificateValidator.CertificateValidation += (validator, e) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($" ⚠️ 서버 인증서 검증 이슈: {e.Error.StatusCode} — {e.Certificate.Subject}");
|
||||||
|
// e.Accept = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
Console.WriteLine("Step 1: Discovering endpoints...");
|
||||||
|
|
||||||
|
// 2. Endpoint 검색
|
||||||
|
var endpointConfig = EndpointConfiguration.Create(config);
|
||||||
|
endpointConfig.OperationTimeout = 10000;
|
||||||
|
|
||||||
|
var discoveryClient = await DiscoveryClient.CreateAsync(
|
||||||
|
new Uri(endpoint),
|
||||||
|
endpointConfig,
|
||||||
|
config,
|
||||||
|
DiagnosticsMasks.None,
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
var endpoints = await discoveryClient.GetEndpointsAsync(null);
|
||||||
|
discoveryClient.Dispose();
|
||||||
|
|
||||||
|
if (endpoints == null || endpoints.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ No endpoints found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
|
||||||
|
foreach (var ep in endpoints)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {ep.EndpointUrl} | Security: {ep.SecurityMode} | Policy: {ep.SecurityPolicyUri?.Split('#').Last()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignAndEncrypt 엔드포인트 우선 선택, 없으면 Sign, 없으면 첫 번째
|
||||||
|
var selectedEndpoint =
|
||||||
|
endpoints.FirstOrDefault(e => e.SecurityMode == MessageSecurityMode.SignAndEncrypt)
|
||||||
|
?? endpoints.FirstOrDefault(e => e.SecurityMode == MessageSecurityMode.Sign)
|
||||||
|
?? endpoints[0];
|
||||||
|
|
||||||
|
Console.WriteLine($"\n선택된 엔드포인트: {selectedEndpoint.EndpointUrl} ({selectedEndpoint.SecurityMode})");
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 2: Creating session...");
|
||||||
|
|
||||||
|
// 3. ConfiguredEndpoint 생성
|
||||||
|
var configuredEndpoint = new ConfiguredEndpoint(
|
||||||
|
null,
|
||||||
|
selectedEndpoint,
|
||||||
|
EndpointConfiguration.Create(config));
|
||||||
|
|
||||||
|
// 4. Session 생성 — UserIdentity에 Windows 계정 사용
|
||||||
|
// Experion R530은 Windows 계정을 OPC UA UserNameIdentityToken으로 인증
|
||||||
|
var userIdentity = new UserIdentity(new UserNameIdentityToken
|
||||||
|
{
|
||||||
|
UserName = userName,
|
||||||
|
DecryptedPassword = System.Text.Encoding.UTF8.GetBytes(password)
|
||||||
|
});
|
||||||
|
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configuredEndpoint,
|
||||||
|
false,
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
userIdentity,
|
||||||
|
null);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected!");
|
||||||
|
Console.WriteLine($" Session ID: {session.SessionId}");
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 3: Reading server info...");
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 4: Checking redundancy...");
|
||||||
|
await CheckRedundancyAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 5: Browsing nodes...");
|
||||||
|
await BrowseNodesAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\n✅ All tests completed!");
|
||||||
|
}
|
||||||
|
catch (ServiceResultException sre)
|
||||||
|
{
|
||||||
|
uint code = (uint)sre.StatusCode;
|
||||||
|
|
||||||
|
// Console.WriteLine($"\n❌ OPC UA 오류: {sre.Message}");
|
||||||
|
Console.WriteLine($" StatusCode: 0x{code:X8} ({code})");
|
||||||
|
|
||||||
|
if (_statusCodeMap.TryGetValue(code, out var info))
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Name: {info.Name}");
|
||||||
|
Console.WriteLine($" Description: {info.Description}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(" ⚠️ statuscode.json에 정의되지 않은 코드입니다.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nClosing session...");
|
||||||
|
await session.CloseAsync();
|
||||||
|
session.Dispose();
|
||||||
|
Console.WriteLine("✅ Session closed");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var state = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_State));
|
||||||
|
Console.WriteLine($" State: {state.Value}");
|
||||||
|
|
||||||
|
var time = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_CurrentTime));
|
||||||
|
Console.WriteLine($" Time: {time.Value}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task CheckRedundancyAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serviceLevel = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServiceLevel));
|
||||||
|
|
||||||
|
byte level = Convert.ToByte(serviceLevel.Value);
|
||||||
|
Console.WriteLine($" Service Level: {level}");
|
||||||
|
|
||||||
|
if (level >= 200)
|
||||||
|
Console.WriteLine(" ✅ PRIMARY server");
|
||||||
|
else if (level > 0)
|
||||||
|
Console.WriteLine(" ⚠️ SECONDARY server");
|
||||||
|
else
|
||||||
|
Console.WriteLine(" ℹ️ STANDALONE");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task BrowseNodesAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var browser = new Browser(session)
|
||||||
|
{
|
||||||
|
BrowseDirection = BrowseDirection.Forward,
|
||||||
|
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
|
||||||
|
IncludeSubtypes = true,
|
||||||
|
NodeClassMask = (int)(NodeClass.Object | NodeClass.Variable)
|
||||||
|
};
|
||||||
|
|
||||||
|
var references = await browser.BrowseAsync(ObjectIds.ObjectsFolder);
|
||||||
|
|
||||||
|
Console.WriteLine($" Found {references.Count} top-level nodes:");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (var r in references)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" {r.DisplayName} ({r.NodeClass})");
|
||||||
|
if (++count >= 5)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" ... and {references.Count - 5} more");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
253
OpcConnectionTest/Program copy.cs.org
Normal file
253
OpcConnectionTest/Program copy.cs.org
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
[Obsolete]
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
|
||||||
|
|
||||||
|
// ⚠️ Experion 서버 IP 주소 수정
|
||||||
|
string endpoint = "opc.tcp://192.168.0.20:4840";
|
||||||
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
|
X509Certificate2 clientCertificate = new X509Certificate2(pfxPath, "");
|
||||||
|
|
||||||
|
Console.WriteLine($"Server: {endpoint}\n");
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. Configuration 생성
|
||||||
|
var config = new ApplicationConfiguration()
|
||||||
|
{
|
||||||
|
ApplicationName = "OPC Test Client",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = "urn:OpcTestClient",
|
||||||
|
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/own"),
|
||||||
|
SubjectName = "CN=OpcTestClient"
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/trusted")
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/issuers")
|
||||||
|
},
|
||||||
|
|
||||||
|
RejectedCertificateStore = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/rejected")
|
||||||
|
},
|
||||||
|
|
||||||
|
AutoAcceptUntrustedCertificates = true,
|
||||||
|
RejectSHA1SignedCertificates = false,
|
||||||
|
AddAppCertToTrustedStore = true
|
||||||
|
},
|
||||||
|
|
||||||
|
TransportConfigurations = new TransportConfigurationCollection(),
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
Console.WriteLine("Step 1: Discovering endpoints...");
|
||||||
|
|
||||||
|
// 2. Endpoint 검색
|
||||||
|
var endpointConfig = EndpointConfiguration.Create(config);
|
||||||
|
endpointConfig.OperationTimeout = 10000;
|
||||||
|
|
||||||
|
var discoveryClient = await DiscoveryClient.CreateAsync(
|
||||||
|
new Uri(endpoint),
|
||||||
|
endpointConfig,
|
||||||
|
config,
|
||||||
|
DiagnosticsMasks.None,
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
var endpoints = await discoveryClient.GetEndpointsAsync(null);
|
||||||
|
discoveryClient.Dispose();
|
||||||
|
|
||||||
|
if (endpoints == null || endpoints.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ No endpoints found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
|
||||||
|
foreach (var ep in endpoints)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {ep.EndpointUrl} ({ep.SecurityMode})");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 2: Creating session...");
|
||||||
|
|
||||||
|
// 3. ConfiguredEndpoint 생성
|
||||||
|
var selectedEndpoint = endpoints[0];
|
||||||
|
var configuredEndpoint = new ConfiguredEndpoint(
|
||||||
|
null,
|
||||||
|
selectedEndpoint,
|
||||||
|
EndpointConfiguration.Create(config));
|
||||||
|
|
||||||
|
// Session.Create 호출 직전에 추가
|
||||||
|
var cert = await config.SecurityConfiguration.ApplicationCertificate.Find(true);
|
||||||
|
if (cert == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ [Internal Error] 코드가 인증서 파일을 찾지 못했습니다!");
|
||||||
|
Console.WriteLine($"확인 경로: {Path.GetFullPath(config.SecurityConfiguration.ApplicationCertificate.StorePath)}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"✅ 인증서 로드 성공: {cert.Subject}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Session 생성 (최신 API)
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configuredEndpoint,
|
||||||
|
false,
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
new UserIdentity(new AnonymousIdentityToken()),
|
||||||
|
null);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected!");
|
||||||
|
Console.WriteLine($" Session ID: {session.SessionId}");
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 3: Reading server info...");
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 4: Checking redundancy...");
|
||||||
|
await CheckRedundancyAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 5: Browsing nodes...");
|
||||||
|
await BrowseNodesAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\n✅ All tests completed!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n❌ Error: {ex.Message}");
|
||||||
|
Console.WriteLine($"Type: {ex.GetType().Name}");
|
||||||
|
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Inner: {ex.InnerException.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nClosing session...");
|
||||||
|
await session.CloseAsync();
|
||||||
|
session.Dispose();
|
||||||
|
Console.WriteLine("✅ Session closed");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Server State
|
||||||
|
var state = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_State));
|
||||||
|
Console.WriteLine($" State: {state.Value}");
|
||||||
|
|
||||||
|
// Server Time
|
||||||
|
var time = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_CurrentTime));
|
||||||
|
Console.WriteLine($" Time: {time.Value}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task CheckRedundancyAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serviceLevel = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServiceLevel));
|
||||||
|
|
||||||
|
byte level = Convert.ToByte(serviceLevel.Value);
|
||||||
|
Console.WriteLine($" Service Level: {level}");
|
||||||
|
|
||||||
|
if (level >= 200)
|
||||||
|
Console.WriteLine(" ✅ PRIMARY server");
|
||||||
|
else if (level > 0)
|
||||||
|
Console.WriteLine(" ⚠️ SECONDARY server");
|
||||||
|
else
|
||||||
|
Console.WriteLine(" ℹ️ STANDALONE");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task BrowseNodesAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var browser = new Browser(session)
|
||||||
|
{
|
||||||
|
BrowseDirection = BrowseDirection.Forward,
|
||||||
|
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
|
||||||
|
IncludeSubtypes = true,
|
||||||
|
NodeClassMask = (int)(NodeClass.Object | NodeClass.Variable)
|
||||||
|
};
|
||||||
|
|
||||||
|
var references = await browser.BrowseAsync(ObjectIds.ObjectsFolder);
|
||||||
|
|
||||||
|
Console.WriteLine($" Found {references.Count} top-level nodes:");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (var r in references)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" {r.DisplayName} ({r.NodeClass})");
|
||||||
|
if (++count >= 5)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" ... and {references.Count - 5} more");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
212
OpcConnectionTest/Program copy.csno2
Normal file
212
OpcConnectionTest/Program copy.csno2
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
public class StatusCodeInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Hex { get; set; } = "";
|
||||||
|
public ulong Decimal { get; set; }
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static Dictionary<uint, StatusCodeInfo> _statusCodeMap = new();
|
||||||
|
|
||||||
|
// statuscode.json 로드 로직
|
||||||
|
static void LoadStatusCodes()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(Directory.GetCurrentDirectory(), "statuscode.json");
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Console.WriteLine("⚠️ statuscode.json 파일을 찾을 수 없습니다. (에러 분석 기능 제한)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
var list = JsonSerializer.Deserialize<List<StatusCodeInfo>>(json);
|
||||||
|
if (list != null)
|
||||||
|
foreach (var item in list)
|
||||||
|
_statusCodeMap[(uint)item.Decimal] = item;
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ StatusCode {_statusCodeMap.Count}개 로드 완료\n");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ statuscode.json 로드 실패: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
LoadStatusCodes();
|
||||||
|
|
||||||
|
// 1. 설정 정보 (UaExpert 정보 기반)
|
||||||
|
string endpointUrl = "opc.tcp://DESKTOP-8VS6SD2:4840";
|
||||||
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
|
string pfxPassword = ""; // 저장된 정보 기반 공백 유지
|
||||||
|
string userName = "mngr";
|
||||||
|
string password = "mngr";
|
||||||
|
|
||||||
|
if (!File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ PFX 파일 없음: {pfxPath}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 인증서 로드 및 애플리케이션 설정
|
||||||
|
var clientCert = new X509Certificate2(
|
||||||
|
pfxPath,
|
||||||
|
pfxPassword,
|
||||||
|
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet
|
||||||
|
);
|
||||||
|
|
||||||
|
var config = new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
ApplicationName = "OpcTestClient",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = "urn:OpcTestClient",
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier { Certificate = clientCert },
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/trusted") },
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/issuers") },
|
||||||
|
RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/rejected") },
|
||||||
|
AutoAcceptUntrustedCertificates = true,
|
||||||
|
AddAppCertToTrustedStore = true
|
||||||
|
},
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
config.CertificateValidator.CertificateValidation += (validator, e) =>
|
||||||
|
{
|
||||||
|
if (e.Error != null && e.Error.StatusCode != StatusCodes.Good)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"인증서 보안 경고 무시(Ignore): {e.Error.StatusCode}");
|
||||||
|
e.Accept = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 3. 엔드포인트 탐색 및 선택 (UaExpert 보안 정책 반영)
|
||||||
|
Console.WriteLine("Step 1: Discovering endpoints...");
|
||||||
|
using (var discovery = DiscoveryClient.Create(new Uri(endpointUrl), EndpointConfiguration.Create(config)))
|
||||||
|
{
|
||||||
|
var endpoints = discovery.GetEndpoints(null);
|
||||||
|
Console.WriteLine($"✅ {endpoints.Count} 엔드포인트 발견");
|
||||||
|
|
||||||
|
// 가장 높은 보안 수준을 가진 엔드포인트 중 Aes256_Sha256_RsaPss 우선 선택
|
||||||
|
var selected = endpoints.OrderByDescending(e => e.SecurityLevel)
|
||||||
|
.FirstOrDefault(e => e.SecurityPolicyUri.Contains("Basic256Sha256"))
|
||||||
|
?? endpoints.OrderByDescending(e => e.SecurityLevel).First();
|
||||||
|
|
||||||
|
Console.WriteLine($"👉 선택된 엔드포인트: {selected.SecurityMode} | {selected.SecurityPolicyUri.Split('#').Last()}");
|
||||||
|
|
||||||
|
var configured = new ConfiguredEndpoint(null, selected, EndpointConfiguration.Create(config));
|
||||||
|
|
||||||
|
// 4. 세션 생성 (mngr 계정)
|
||||||
|
Console.WriteLine("\nStep 2: Creating session with user identity...");
|
||||||
|
|
||||||
|
// 패스워드를 byte[]로 요구하는 최신 SDK 방식 적용
|
||||||
|
var identity = new UserIdentity(userName, Encoding.UTF8.GetBytes(password));
|
||||||
|
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configured,
|
||||||
|
false, // updateBeforeConnect
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
identity,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected! SessionID: {session.SessionId}");
|
||||||
|
|
||||||
|
// 5. 서버 상태 확인
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
|
||||||
|
// 6. UaExpert에서 확인한 하니웰 실제 태그 데이터 읽기
|
||||||
|
await ReadHoneywellTagAsync(session);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ServiceResultException sre)
|
||||||
|
{
|
||||||
|
uint code = (uint)sre.StatusCode;
|
||||||
|
Console.WriteLine($"\n❌ OPC UA 오류: {sre.Message}");
|
||||||
|
Console.WriteLine($" StatusCode: 0x{code:X8}");
|
||||||
|
|
||||||
|
if (_statusCodeMap.TryGetValue(code, out var info))
|
||||||
|
Console.WriteLine($" Name: {info.Name}\n Description: {info.Description}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n❌ 일반 오류 발생: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
await session.CloseAsync();
|
||||||
|
session.Dispose();
|
||||||
|
Console.WriteLine("\n✅ Session closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 서버 기본 정보 읽기
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
var state = await session.ReadValueAsync(Variables.Server_ServerStatus_State);
|
||||||
|
var time = await session.ReadValueAsync(Variables.Server_ServerStatus_CurrentTime);
|
||||||
|
Console.WriteLine($"\n[Server Status]\n - State: {state.Value}\n - Time: {time.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🎯 하니웰 특정 태그 읽기 (UaExpert 데이터 기반)
|
||||||
|
static async Task ReadHoneywellTagAsync(ISession session)
|
||||||
|
{
|
||||||
|
string nodeId = "ns=1;s=shinam:p-6102.hzset.fieldvalue";
|
||||||
|
Console.WriteLine($"\nStep 3: Reading Honeywell Tag [{nodeId}]...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await session.ReadValueAsync(nodeId);
|
||||||
|
|
||||||
|
if (StatusCode.IsGood(result.StatusCode))
|
||||||
|
{
|
||||||
|
Console.WriteLine("========================================");
|
||||||
|
Console.WriteLine($"🟢 TAG VALUE : {result.Value}");
|
||||||
|
Console.WriteLine($"🟡 DATATYPE : {result.WrappedValue.TypeInfo.BuiltInType}");
|
||||||
|
Console.WriteLine($"🔵 TIMESTAMP : {result.SourceTimestamp.ToLocalTime()}");
|
||||||
|
Console.WriteLine($"⚪️ STATUS : {result.StatusCode}");
|
||||||
|
Console.WriteLine("========================================");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ 읽기 실패: {result.StatusCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ 태그 읽기 중 예외 발생: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,191 +1,145 @@
|
|||||||
// cd ~/projects/OpcConnectionTest
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
// 기존 파일 삭제
|
using System.IO;
|
||||||
// rm Program.cs
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
// # 새 파일 생성
|
using System.Threading;
|
||||||
//cat > Program.cs << 'EOF'
|
using System.Threading.Tasks;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text.Json;
|
||||||
using Opc.Ua;
|
using Opc.Ua;
|
||||||
using Opc.Ua.Client;
|
using Opc.Ua.Client;
|
||||||
using Opc.Ua.Configuration;
|
|
||||||
|
|
||||||
namespace OpcConnectionTest
|
namespace OpcConnectionTest
|
||||||
{
|
{
|
||||||
|
public class StatusCodeInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Hex { get; set; } = "";
|
||||||
|
public ulong Decimal { get; set; }
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
|
static Dictionary<string, StatusCodeInfo> _statusCodeMap = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
static void LoadStatusCodes()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(Directory.GetCurrentDirectory(), "statuscode.json");
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||||
|
var list = JsonSerializer.Deserialize<List<StatusCodeInfo>>(json, options);
|
||||||
|
if (list != null) {
|
||||||
|
foreach (var item in list) _statusCodeMap[item.Hex] = item;
|
||||||
|
Console.WriteLine($"✅ {_statusCodeMap.Count}개의 에러 코드 정의 로드 완료.");
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async Task Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
|
LoadStatusCodes();
|
||||||
|
|
||||||
// ⚠️ Experion 서버 IP 주소 수정
|
// 1. 핵심 변수 (서버 이름 사칭 방지)
|
||||||
string primaryEndpoint = "opc.tcp://192.168.0.20:4840";
|
string serverHostName = "192.168.0.20"; //DESKTOP-8VS6SD2
|
||||||
string secondaryEndpoint = "opc.tcp://192.168.1.20:4840";
|
string clientHostName = "dbsvr";
|
||||||
|
string endpointUrl = $"opc.tcp://{serverHostName}:4840";
|
||||||
|
string applicationUri = $"urn:{clientHostName}:OpcTestClient";
|
||||||
|
|
||||||
Console.WriteLine($"Primary: {primaryEndpoint}");
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
Console.WriteLine($"Secondary: {secondaryEndpoint}\n");
|
string pfxPassword = "";
|
||||||
|
string userName = "mngr";
|
||||||
|
string password = "mngr";
|
||||||
|
|
||||||
|
// 필수 폴더들 생성 (TrustedIssuer 포함)
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(pfxPath)!);
|
||||||
|
Directory.CreateDirectory("pki/trusted/certs");
|
||||||
|
Directory.CreateDirectory("pki/issuers/certs"); // ← 이 경로가 필요함
|
||||||
|
Directory.CreateDirectory("pki/rejected/certs");
|
||||||
|
|
||||||
|
X509Certificate2? clientCert = null;
|
||||||
|
if (!File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
var builder = CertificateFactory.CreateCertificate(
|
||||||
|
applicationUri, "OpcTestClient", $"CN=OpcTestClient, O=MyCompany",
|
||||||
|
new List<string> { "localhost", clientHostName, "192.168.0.5", "192.168.0.102" }
|
||||||
|
);
|
||||||
|
clientCert = builder.CreateForRSA();
|
||||||
|
File.WriteAllBytes(pfxPath, clientCert.Export(X509ContentType.Pfx, pfxPassword));
|
||||||
|
Console.WriteLine($"✨ 새 인증서 생성됨: {applicationUri}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientCert = new X509Certificate2(pfxPath, pfxPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
ApplicationName = "OpcTestClient",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = applicationUri,
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier { Certificate = clientCert },
|
||||||
|
// ⚠️ 에러 발생했던 지점: 아래 3개 경로가 모두 명시되어야 함
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/trusted") },
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/issuers") },
|
||||||
|
RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = Path.GetFullPath("pki/rejected") },
|
||||||
|
AutoAcceptUntrustedCertificates = true,
|
||||||
|
AddAppCertToTrustedStore = true
|
||||||
|
},
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
config.CertificateValidator.CertificateValidation += (v, e) => { if (e.Error.StatusCode != StatusCodes.Good) e.Accept = true; };
|
||||||
|
|
||||||
ISession? session = null;
|
ISession? session = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var config = new ApplicationConfiguration()
|
Console.WriteLine($"Step 1: Connecting to {endpointUrl}...");
|
||||||
|
var endpointConfig = EndpointConfiguration.Create(config);
|
||||||
|
using (var discovery = await DiscoveryClient.CreateAsync(config, new Uri(endpointUrl), DiagnosticsMasks.All, CancellationToken.None))
|
||||||
{
|
{
|
||||||
ApplicationName = "OPC Test",
|
var endpoints = await discovery.GetEndpointsAsync(null);
|
||||||
ApplicationType = ApplicationType.Client,
|
var selected = endpoints.OrderByDescending(e => e.SecurityLevel)
|
||||||
ApplicationUri = "urn:OpcTest",
|
.FirstOrDefault(e => e.SecurityPolicyUri.Contains("Basic256Sha256")) ?? endpoints[0];
|
||||||
SecurityConfiguration = new SecurityConfiguration
|
|
||||||
{
|
|
||||||
ApplicationCertificate = new CertificateIdentifier
|
|
||||||
{
|
|
||||||
StoreType = "Directory",
|
|
||||||
StorePath = "OPC Foundation/CertificateStores/MachineDefault"
|
|
||||||
},
|
|
||||||
AutoAcceptUntrustedCertificates = true,
|
|
||||||
RejectSHA1SignedCertificates = false
|
|
||||||
},
|
|
||||||
TransportConfigurations = new TransportConfigurationCollection(),
|
|
||||||
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
|
||||||
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
|
||||||
};
|
|
||||||
|
|
||||||
await config.ValidateAsync(ApplicationType.Client);
|
Console.WriteLine($"🔍 정책 선택됨: {selected.SecurityPolicyUri}");
|
||||||
|
var endpoint = new ConfiguredEndpoint(null, selected, endpointConfig);
|
||||||
|
|
||||||
Console.WriteLine("Step 1: Discovering endpoints...");
|
Console.WriteLine("Step 2: Creating session...");
|
||||||
var endpoints = await DiscoverAsync(config, primaryEndpoint);
|
var identity = new UserIdentity(userName, Encoding.UTF8.GetBytes(password));
|
||||||
|
#pragma warning disable CS0618
|
||||||
if (endpoints.Count == 0)
|
session = await Session.Create(config, endpoint, false, "OpcTestSession", 60000, identity, null);
|
||||||
{
|
#pragma warning restore CS0618
|
||||||
Console.WriteLine("❌ No endpoints found!");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
Console.WriteLine($"✅ Connected! SessionID: {session.SessionId}");
|
||||||
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
|
var result = await session.ReadValueAsync("ns=1;s=shinam:p-6102.hzset.fieldvalue");
|
||||||
|
Console.WriteLine($"🟢 TAG VALUE: {result.Value}");
|
||||||
Console.WriteLine("\nStep 2: Connecting...");
|
|
||||||
session = await ConnectAsync(config, endpoints[0]);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("❌ Connection failed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"✅ Connected! ID: {session.SessionId}");
|
|
||||||
|
|
||||||
Console.WriteLine("\nStep 3: Reading server info...");
|
|
||||||
await ReadInfoAsync(session);
|
|
||||||
|
|
||||||
Console.WriteLine("\nStep 4: Checking redundancy...");
|
|
||||||
await CheckRedundancyAsync(session);
|
|
||||||
|
|
||||||
Console.WriteLine("\n✅ Test completed!");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"\n❌ Error: {ex.Message}");
|
if (ex is ServiceResultException sre)
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (session != null)
|
|
||||||
{
|
{
|
||||||
await session.CloseAsync();
|
string hexCode = $"0x{((uint)sre.StatusCode):X8}";
|
||||||
session.Dispose();
|
Console.WriteLine($"\n❌ OPC UA 서비스 오류: {hexCode}");
|
||||||
|
if (_statusCodeMap.TryGetValue(hexCode, out var info)) {
|
||||||
|
Console.WriteLine($"👉 에러명: {info.Name}");
|
||||||
|
Console.WriteLine($"👉 설 명: {info.Description}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else Console.WriteLine($"❌ 오류: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
finally { if (session != null) { await session.CloseAsync(); session.Dispose(); } }
|
||||||
Console.WriteLine("\nPress Enter to exit...");
|
Console.WriteLine("\n엔터를 누르면 종료됩니다...");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task<EndpointDescriptionCollection> DiscoverAsync(
|
|
||||||
ApplicationConfiguration config, string url)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var epConfig = EndpointConfiguration.Create(config);
|
|
||||||
epConfig.OperationTimeout = 10000;
|
|
||||||
|
|
||||||
var client = await DiscoveryClient.CreateAsync(
|
|
||||||
new Uri(url), epConfig, config,
|
|
||||||
DiagnosticsMasks.None, CancellationToken.None);
|
|
||||||
|
|
||||||
var eps = await client.GetEndpointsAsync(null);
|
|
||||||
client.Dispose();
|
|
||||||
return eps;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return new EndpointDescriptionCollection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async Task<ISession?> ConnectAsync(
|
|
||||||
ApplicationConfiguration config, EndpointDescription ep)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var epConfig = EndpointConfiguration.Create(config);
|
|
||||||
var configEp = new ConfiguredEndpoint(null, ep, epConfig);
|
|
||||||
|
|
||||||
var channel = SessionChannel.Create(
|
|
||||||
config,
|
|
||||||
configEp.Description,
|
|
||||||
configEp.Configuration,
|
|
||||||
X509CertificateValidator.TolerateAll,
|
|
||||||
null);
|
|
||||||
|
|
||||||
var sess = new Session(channel, config, configEp, null);
|
|
||||||
|
|
||||||
await sess.OpenAsync(
|
|
||||||
config.ApplicationName, 60000,
|
|
||||||
new UserIdentity(new AnonymousIdentityToken()),
|
|
||||||
null, CancellationToken.None);
|
|
||||||
|
|
||||||
return sess;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async Task ReadInfoAsync(ISession s)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var v1 = await s.ReadValueAsync(new NodeId(Variables.Server_ServerStatus_State));
|
|
||||||
Console.WriteLine($" State: {v1.Value}");
|
|
||||||
|
|
||||||
var v2 = await s.ReadValueAsync(new NodeId(Variables.Server_ServerStatus_CurrentTime));
|
|
||||||
Console.WriteLine($" Time: {v2.Value}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" Failed: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async Task CheckRedundancyAsync(ISession s)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var v = await s.ReadValueAsync(new NodeId(Variables.Server_ServiceLevel));
|
|
||||||
byte level = Convert.ToByte(v.Value);
|
|
||||||
Console.WriteLine($" Service Level: {level}");
|
|
||||||
|
|
||||||
if (level >= 200)
|
|
||||||
Console.WriteLine(" ✅ PRIMARY server");
|
|
||||||
else if (level > 0)
|
|
||||||
Console.WriteLine(" ⚠️ SECONDARY server");
|
|
||||||
else
|
|
||||||
Console.WriteLine(" ℹ️ STANDALONE");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" Failed: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
187
OpcConnectionTest/Program.cs.3wNoError
Normal file
187
OpcConnectionTest/Program.cs.3wNoError
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
public class StatusCodeInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Hex { get; set; } = "";
|
||||||
|
public ulong Decimal { get; set; }
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static Dictionary<uint, StatusCodeInfo> _statusCodeMap = new();
|
||||||
|
|
||||||
|
static void LoadStatusCodes()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(Directory.GetCurrentDirectory(), "statuscode.json");
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Console.WriteLine("⚠️ statuscode.json 파일을 찾을 수 없습니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
var list = JsonSerializer.Deserialize<List<StatusCodeInfo>>(json);
|
||||||
|
if (list != null)
|
||||||
|
foreach (var item in list)
|
||||||
|
_statusCodeMap[(uint)item.Decimal] = item;
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ StatusCode {_statusCodeMap.Count}개 로드 완료\n");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ statuscode.json 로드 실패: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
LoadStatusCodes();
|
||||||
|
|
||||||
|
string endpointUrl = "opc.tcp://192.168.0.20:4840";
|
||||||
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
|
string pfxPassword = "";
|
||||||
|
string userName = "mngr";
|
||||||
|
string password = "mngr";
|
||||||
|
|
||||||
|
if (!File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ PFX 파일 없음: {pfxPath}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientCert = new X509Certificate2(
|
||||||
|
pfxPath,
|
||||||
|
pfxPassword,
|
||||||
|
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!clientCert.HasPrivateKey)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ 인증서에 개인키 없음");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
ApplicationName = "OPC Test Client",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/own"),
|
||||||
|
Certificate = clientCert
|
||||||
|
},
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/trusted")
|
||||||
|
},
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/issuers")
|
||||||
|
},
|
||||||
|
RejectedCertificateStore = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/rejected")
|
||||||
|
},
|
||||||
|
AutoAcceptUntrustedCertificates = true
|
||||||
|
},
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
config.CertificateValidator.CertificateValidation += (s, e) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"⚠️ 서버 인증서 검증 실패: {e.Error.StatusCode} - {e.Certificate.Subject}");
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("Step 1: Discovering endpoints...");
|
||||||
|
var discovery = DiscoveryClient.Create(new Uri(endpointUrl));
|
||||||
|
var endpoints = discovery.GetEndpoints(null);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ {endpoints.Count} 엔드포인트 발견");
|
||||||
|
|
||||||
|
foreach (var ep in endpoints)
|
||||||
|
Console.WriteLine($" - {ep.EndpointUrl} | {ep.SecurityMode} | {ep.SecurityPolicyUri?.Split('#').Last()}");
|
||||||
|
|
||||||
|
// AES256/SHA256 우선 선택
|
||||||
|
var selected = endpoints.FirstOrDefault(ep =>
|
||||||
|
ep.SecurityMode == MessageSecurityMode.SignAndEncrypt &&
|
||||||
|
ep.SecurityPolicyUri.EndsWith("Basic256Sha256"))
|
||||||
|
?? endpoints.First();
|
||||||
|
|
||||||
|
Console.WriteLine($"\n선택된 엔드포인트: {selected.EndpointUrl} ({selected.SecurityMode})");
|
||||||
|
|
||||||
|
var configured = new ConfiguredEndpoint(null, selected, EndpointConfiguration.Create(config));
|
||||||
|
|
||||||
|
// ✅ Session.CreateAsync 사용
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configured,
|
||||||
|
false,
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
new UserIdentity(userName, Encoding.UTF8.GetBytes(password)),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected! SessionID: {session.SessionId}");
|
||||||
|
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
}
|
||||||
|
catch (ServiceResultException sre)
|
||||||
|
{
|
||||||
|
uint code = (uint)sre.StatusCode;
|
||||||
|
Console.WriteLine($"❌ OPC UA 오류: {sre.Message}");
|
||||||
|
Console.WriteLine($" StatusCode: 0x{code:X8}");
|
||||||
|
|
||||||
|
if (_statusCodeMap.TryGetValue(code, out var info))
|
||||||
|
Console.WriteLine($" Name: {info.Name}\n Description: {info.Description}");
|
||||||
|
else
|
||||||
|
Console.WriteLine(" ⚠️ statuscode.json에 정의되지 않은 코드입니다.");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
await session.CloseAsync();
|
||||||
|
session.Dispose();
|
||||||
|
Console.WriteLine("✅ Session closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
var state = await session.ReadValueAsync(Variables.Server_ServerStatus_State);
|
||||||
|
var time = await session.ReadValueAsync(Variables.Server_ServerStatus_CurrentTime);
|
||||||
|
|
||||||
|
Console.WriteLine($"Server State: {state.Value}");
|
||||||
|
Console.WriteLine($"Current Time: {time.Value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
274
OpcConnectionTest/Program.cs.fail1
Normal file
274
OpcConnectionTest/Program.cs.fail1
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
[Obsolete]
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
|
||||||
|
|
||||||
|
// ⚠️ Experion 서버 IP 주소 수정
|
||||||
|
string endpoint = "opc.tcp://192.168.0.20:4840";
|
||||||
|
string pfxPath = Path.Combine(Directory.GetCurrentDirectory(), "pki/own/certs/OpcTestClient.pfx");
|
||||||
|
|
||||||
|
// PFX 파일 존재 여부 먼저 확인
|
||||||
|
if (!File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ PFX 파일을 찾을 수 없습니다: {pfxPath}");
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PFX를 직접 로드 (Exportable 플래그 필수 — OPC UA 서명에 개인키 접근 필요)
|
||||||
|
X509Certificate2 clientCertificate = new X509Certificate2(
|
||||||
|
pfxPath,
|
||||||
|
"",
|
||||||
|
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
||||||
|
|
||||||
|
Console.WriteLine($"Server: {endpoint}");
|
||||||
|
Console.WriteLine($"Certificate: {clientCertificate.Subject}\n");
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. Configuration 생성
|
||||||
|
var config = new ApplicationConfiguration()
|
||||||
|
{
|
||||||
|
ApplicationName = "OPC Test Client",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = "urn:OpcTestClient",
|
||||||
|
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/own"),
|
||||||
|
SubjectName = "CN=OpcTestClient",
|
||||||
|
// PFX를 직접 주입 — Directory Store 탐색 없이 이 인증서를 사용
|
||||||
|
Certificate = clientCertificate
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/trusted")
|
||||||
|
},
|
||||||
|
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/issuers")
|
||||||
|
},
|
||||||
|
|
||||||
|
RejectedCertificateStore = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.GetFullPath("pki/rejected")
|
||||||
|
},
|
||||||
|
|
||||||
|
AutoAcceptUntrustedCertificates = true,
|
||||||
|
RejectSHA1SignedCertificates = false,
|
||||||
|
AddAppCertToTrustedStore = true
|
||||||
|
},
|
||||||
|
|
||||||
|
TransportConfigurations = new TransportConfigurationCollection(),
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
// 인증서 로드 확인 (Find 대신 직접 참조)
|
||||||
|
var cert = config.SecurityConfiguration.ApplicationCertificate.Certificate;
|
||||||
|
if (cert == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ [Internal Error] 인증서 주입에 실패했습니다!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Console.WriteLine($"✅ 인증서 로드 성공: {cert.Subject}");
|
||||||
|
Console.WriteLine($" 유효기간: {cert.NotBefore:yyyy-MM-dd} ~ {cert.NotAfter:yyyy-MM-dd}");
|
||||||
|
Console.WriteLine($" 개인키 포함: {cert.HasPrivateKey}");
|
||||||
|
|
||||||
|
if (!cert.HasPrivateKey)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ 개인키가 없습니다. PFX 파일 또는 KeyStorageFlags를 확인하세요.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 1: Discovering endpoints...");
|
||||||
|
|
||||||
|
// 2. Endpoint 검색
|
||||||
|
var endpointConfig = EndpointConfiguration.Create(config);
|
||||||
|
endpointConfig.OperationTimeout = 10000;
|
||||||
|
|
||||||
|
var discoveryClient = await DiscoveryClient.CreateAsync(
|
||||||
|
new Uri(endpoint),
|
||||||
|
endpointConfig,
|
||||||
|
config,
|
||||||
|
DiagnosticsMasks.None,
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
var endpoints = await discoveryClient.GetEndpointsAsync(null);
|
||||||
|
discoveryClient.Dispose();
|
||||||
|
|
||||||
|
if (endpoints == null || endpoints.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ No endpoints found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
|
||||||
|
foreach (var ep in endpoints)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {ep.EndpointUrl} ({ep.SecurityMode})");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 2: Creating session...");
|
||||||
|
|
||||||
|
// 3. ConfiguredEndpoint 생성
|
||||||
|
var selectedEndpoint = endpoints[0];
|
||||||
|
var configuredEndpoint = new ConfiguredEndpoint(
|
||||||
|
null,
|
||||||
|
selectedEndpoint,
|
||||||
|
EndpointConfiguration.Create(config));
|
||||||
|
|
||||||
|
// 4. Session 생성
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configuredEndpoint,
|
||||||
|
false,
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
new UserIdentity(new AnonymousIdentityToken()),
|
||||||
|
null);
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected!");
|
||||||
|
Console.WriteLine($" Session ID: {session.SessionId}");
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 3: Reading server info...");
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 4: Checking redundancy...");
|
||||||
|
await CheckRedundancyAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 5: Browsing nodes...");
|
||||||
|
await BrowseNodesAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\n✅ All tests completed!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n❌ Error: {ex.Message}");
|
||||||
|
Console.WriteLine($"Type: {ex.GetType().Name}");
|
||||||
|
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Inner: {ex.InnerException.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nClosing session...");
|
||||||
|
await session.CloseAsync();
|
||||||
|
session.Dispose();
|
||||||
|
Console.WriteLine("✅ Session closed");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Server State
|
||||||
|
var state = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_State));
|
||||||
|
Console.WriteLine($" State: {state.Value}");
|
||||||
|
|
||||||
|
// Server Time
|
||||||
|
var time = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServerStatus_CurrentTime));
|
||||||
|
Console.WriteLine($" Time: {time.Value}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task CheckRedundancyAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serviceLevel = await session.ReadValueAsync(
|
||||||
|
new NodeId(Variables.Server_ServiceLevel));
|
||||||
|
|
||||||
|
byte level = Convert.ToByte(serviceLevel.Value);
|
||||||
|
Console.WriteLine($" Service Level: {level}");
|
||||||
|
|
||||||
|
if (level >= 200)
|
||||||
|
Console.WriteLine(" ✅ PRIMARY server");
|
||||||
|
else if (level > 0)
|
||||||
|
Console.WriteLine(" ⚠️ SECONDARY server");
|
||||||
|
else
|
||||||
|
Console.WriteLine(" ℹ️ STANDALONE");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task BrowseNodesAsync(ISession session)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var browser = new Browser(session)
|
||||||
|
{
|
||||||
|
BrowseDirection = BrowseDirection.Forward,
|
||||||
|
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
|
||||||
|
IncludeSubtypes = true,
|
||||||
|
NodeClassMask = (int)(NodeClass.Object | NodeClass.Variable)
|
||||||
|
};
|
||||||
|
|
||||||
|
var references = await browser.BrowseAsync(ObjectIds.ObjectsFolder);
|
||||||
|
|
||||||
|
Console.WriteLine($" Found {references.Count} top-level nodes:");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (var r in references)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" {r.DisplayName} ({r.NodeClass})");
|
||||||
|
if (++count >= 5)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" ... and {references.Count - 5} more");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
196
OpcConnectionTest/Program.cs.problem3
Normal file
196
OpcConnectionTest/Program.cs.problem3
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
using Opc.Ua;
|
||||||
|
using Opc.Ua.Client;
|
||||||
|
using Opc.Ua.Configuration;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace OpcConnectionTest
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
|
||||||
|
|
||||||
|
// 1. 기본 경로 및 설정 정보
|
||||||
|
string serverUrl = "opc.tcp://192.168.0.20:4840";
|
||||||
|
string basePkiPath = Path.GetFullPath("pki");
|
||||||
|
string pfxPath = Path.Combine(basePkiPath, "own/certs/OpcTestClient.pfx");
|
||||||
|
|
||||||
|
// 필수 폴더 자동 생성 (Issuer/Rejected 저장소 에러 방지)
|
||||||
|
Directory.CreateDirectory(Path.Combine(basePkiPath, "issuers/certs"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(basePkiPath, "rejected/certs"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(basePkiPath, "trusted/certs"));
|
||||||
|
|
||||||
|
Console.WriteLine($"Server: {serverUrl}");
|
||||||
|
Console.WriteLine($"PKI Root: {basePkiPath}\n");
|
||||||
|
|
||||||
|
ISession? session = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 2. Application Configuration 설정
|
||||||
|
var config = new ApplicationConfiguration()
|
||||||
|
{
|
||||||
|
ApplicationName = "OpcTestClient",
|
||||||
|
ApplicationType = ApplicationType.Client,
|
||||||
|
ApplicationUri = "urn:OpcTestClient",
|
||||||
|
|
||||||
|
SecurityConfiguration = new SecurityConfiguration
|
||||||
|
{
|
||||||
|
ApplicationCertificate = new CertificateIdentifier
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.Combine(basePkiPath, "own"),
|
||||||
|
SubjectName = "CN=OpcTestClient"
|
||||||
|
},
|
||||||
|
TrustedPeerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.Combine(basePkiPath, "trusted")
|
||||||
|
},
|
||||||
|
// 💡 중요: Issuer와 Rejected 경로를 명시해야 에러가 나지 않습니다.
|
||||||
|
TrustedIssuerCertificates = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.Combine(basePkiPath, "issuers")
|
||||||
|
},
|
||||||
|
RejectedCertificateStore = new CertificateTrustList
|
||||||
|
{
|
||||||
|
StoreType = "Directory",
|
||||||
|
StorePath = Path.Combine(basePkiPath, "rejected")
|
||||||
|
},
|
||||||
|
AutoAcceptUntrustedCertificates = true,
|
||||||
|
RejectSHA1SignedCertificates = false,
|
||||||
|
AddAppCertToTrustedStore = true
|
||||||
|
},
|
||||||
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
||||||
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 설정 검증
|
||||||
|
await config.ValidateAsync(ApplicationType.Client);
|
||||||
|
|
||||||
|
// 3. 인증서 수동 주입 (리눅스 PFX 인식 해결)
|
||||||
|
if (File.Exists(pfxPath))
|
||||||
|
{
|
||||||
|
X509Certificate2 clientCertificate = new X509Certificate2(pfxPath, "");
|
||||||
|
config.SecurityConfiguration.ApplicationCertificate.Certificate = clientCertificate;
|
||||||
|
Console.WriteLine($"✅ 인증서 수동 로드 성공: {clientCertificate.Subject}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ PFX 파일을 찾을 수 없습니다! 경로 확인: {pfxPath}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Endpoint 검색
|
||||||
|
Console.WriteLine("\nStep 1: Discovering endpoints...");
|
||||||
|
var endpointConfig = EndpointConfiguration.Create(config);
|
||||||
|
|
||||||
|
using (var discoveryClient = DiscoveryClient.Create(new Uri(serverUrl), endpointConfig))
|
||||||
|
{
|
||||||
|
var endpoints = discoveryClient.GetEndpoints(null);
|
||||||
|
|
||||||
|
if (endpoints == null || endpoints.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("❌ No endpoints found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
|
||||||
|
|
||||||
|
// 가장 높은 보안 수준의 엔드포인트 선택
|
||||||
|
var selectedEndpoint = endpoints.OrderByDescending(e => e.SecurityLevel).First();
|
||||||
|
Console.WriteLine($"👉 Selected: {selectedEndpoint.SecurityMode} | {selectedEndpoint.SecurityPolicyUri}");
|
||||||
|
|
||||||
|
// 5. Session 생성 (mngr 계정)
|
||||||
|
Console.WriteLine("\nStep 2: Creating session with mngr account...");
|
||||||
|
|
||||||
|
var token = new UserNameIdentityToken
|
||||||
|
{
|
||||||
|
UserName = "mngr",
|
||||||
|
DecryptedPassword = System.Text.Encoding.UTF8.GetBytes("mngr")
|
||||||
|
};
|
||||||
|
|
||||||
|
var userIdentity = new UserIdentity(token);
|
||||||
|
var configuredEndpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfig);
|
||||||
|
|
||||||
|
session = await Session.Create(
|
||||||
|
config,
|
||||||
|
configuredEndpoint,
|
||||||
|
updateBeforeConnect: true,
|
||||||
|
"OPC Test Session",
|
||||||
|
60000,
|
||||||
|
userIdentity,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"✅ Connected! Session ID: {session.SessionId}");
|
||||||
|
|
||||||
|
// 6. 데이터 읽기 및 브라우징 테스트
|
||||||
|
Console.WriteLine("\nStep 3: Reading server info...");
|
||||||
|
await ReadServerInfoAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 4: Checking redundancy...");
|
||||||
|
await CheckRedundancyAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\nStep 5: Browsing nodes...");
|
||||||
|
await BrowseNodesAsync(session);
|
||||||
|
|
||||||
|
Console.WriteLine("\n✅ All tests completed successfully!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n❌ Error: {ex.Message}");
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
Console.WriteLine($" Inner: {ex.InnerException.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
await session.CloseAsync();
|
||||||
|
Console.WriteLine("\nSession closed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress Enter to exit...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 헬퍼 메서드들 ---
|
||||||
|
static async Task ReadServerInfoAsync(ISession session)
|
||||||
|
{
|
||||||
|
var state = await session.ReadValueAsync(new NodeId(Variables.Server_ServerStatus_State));
|
||||||
|
var time = await session.ReadValueAsync(new NodeId(Variables.Server_ServerStatus_CurrentTime));
|
||||||
|
Console.WriteLine($" Server State: {state.Value}");
|
||||||
|
Console.WriteLine($" Server Time: {time.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task CheckRedundancyAsync(ISession session)
|
||||||
|
{
|
||||||
|
var serviceLevel = await session.ReadValueAsync(new NodeId(Variables.Server_ServiceLevel));
|
||||||
|
byte level = Convert.ToByte(serviceLevel.Value);
|
||||||
|
string status = level >= 200 ? "PRIMARY" : (level > 0 ? "SECONDARY" : "STANDALONE");
|
||||||
|
Console.WriteLine($" Service Level: {level} ({status})");
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task BrowseNodesAsync(ISession session)
|
||||||
|
{
|
||||||
|
var browser = new Browser(session)
|
||||||
|
{
|
||||||
|
BrowseDirection = BrowseDirection.Forward,
|
||||||
|
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
|
||||||
|
IncludeSubtypes = true,
|
||||||
|
NodeClassMask = (int)(NodeClass.Object | NodeClass.Variable)
|
||||||
|
};
|
||||||
|
|
||||||
|
var references = await browser.BrowseAsync(ObjectIds.ObjectsFolder);
|
||||||
|
Console.WriteLine($" Found {references.Count} nodes in Objects folder. Top 5:");
|
||||||
|
foreach (var r in references.Take(5))
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {r.DisplayName} ({r.NodeClass})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
OpcConnectionTest/bin/Debug/net8.0/BitFaster.Caching.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/BitFaster.Caching.dll
Executable file
Binary file not shown.
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Options.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Options.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Newtonsoft.Json.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Newtonsoft.Json.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Client.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Client.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Configuration.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Configuration.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Core.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Core.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Client.Common.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Client.Common.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Server.Common.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Server.Common.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Security.Certificates.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Security.Certificates.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Server.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Server.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Types.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Types.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest
Executable file
Binary file not shown.
442
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.deps.json
Normal file
442
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.deps.json
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
{
|
||||||
|
"runtimeTarget": {
|
||||||
|
"name": ".NETCoreApp,Version=v8.0",
|
||||||
|
"signature": ""
|
||||||
|
},
|
||||||
|
"compilationOptions": {},
|
||||||
|
"targets": {
|
||||||
|
".NETCoreApp,Version=v8.0": {
|
||||||
|
"OpcConnectionTest/1.0.0": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Client": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"OpcConnectionTest.dll": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BitFaster.Caching/2.5.4": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net6.0/BitFaster.Caching.dll": {
|
||||||
|
"assemblyVersion": "2.5.4.0",
|
||||||
|
"fileVersion": "2.5.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection/10.0.2": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.DependencyInjection.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging/10.0.2": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection": "10.0.2",
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions": "10.0.2",
|
||||||
|
"Microsoft.Extensions.Options": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.Logging.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions/10.0.2": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2",
|
||||||
|
"System.Diagnostics.DiagnosticSource": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Options/10.0.2": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2",
|
||||||
|
"Microsoft.Extensions.Primitives": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.Options.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Primitives/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.Primitives.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Newtonsoft.Json/13.0.4": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net6.0/Newtonsoft.Json.dll": {
|
||||||
|
"assemblyVersion": "13.0.0.0",
|
||||||
|
"fileVersion": "13.0.4.30916"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Client": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Configuration": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Server.Common": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Server": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Types": "1.5.378.106"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Client/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"BitFaster.Caching": "2.5.4",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Configuration": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Client.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Configuration.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Logging": "10.0.2",
|
||||||
|
"Newtonsoft.Json": "13.0.4",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Types": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Core.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Client": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Gds.Client.Common.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Server.Common/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Server": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Gds.Server.Common.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Types": "1.5.378.106",
|
||||||
|
"System.Collections.Immutable": "10.0.2",
|
||||||
|
"System.Diagnostics.DiagnosticSource": "10.0.2",
|
||||||
|
"System.Formats.Asn1": "10.0.2",
|
||||||
|
"System.Text.Json": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Security.Certificates.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Configuration": "1.5.378.106",
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core": "1.5.378.106"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Server.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Types/1.5.378.106": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions": "10.0.2",
|
||||||
|
"System.Collections.Immutable": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Opc.Ua.Types.dll": {
|
||||||
|
"assemblyVersion": "1.5.378.0",
|
||||||
|
"fileVersion": "1.5.378.106"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.Collections.Immutable.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Diagnostics.DiagnosticSource/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.Diagnostics.DiagnosticSource.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Formats.Asn1/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.Formats.Asn1.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.IO.Pipelines/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.IO.Pipelines.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Text.Encodings.Web/10.0.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.Text.Encodings.Web.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtimeTargets": {
|
||||||
|
"runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll": {
|
||||||
|
"rid": "browser",
|
||||||
|
"assetType": "runtime",
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Text.Json/10.0.2": {
|
||||||
|
"dependencies": {
|
||||||
|
"System.IO.Pipelines": "10.0.2",
|
||||||
|
"System.Text.Encodings.Web": "10.0.2"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/System.Text.Json.dll": {
|
||||||
|
"assemblyVersion": "10.0.0.0",
|
||||||
|
"fileVersion": "10.0.225.61305"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"OpcConnectionTest/1.0.0": {
|
||||||
|
"type": "project",
|
||||||
|
"serviceable": false,
|
||||||
|
"sha512": ""
|
||||||
|
},
|
||||||
|
"BitFaster.Caching/2.5.4": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-1QroTY1PVCZOSG9FnkkCrmCKk/+bZCgI/YXq376HnYwUDJ4Ho0EaV4YaA/5v5WYLnwIwIO7RZkdWbg9pxIpueQ==",
|
||||||
|
"path": "bitfaster.caching/2.5.4",
|
||||||
|
"hashPath": "bitfaster.caching.2.5.4.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-J/Zmp6fY93JbaiZ11ckWvcyxMPjD6XVwIHQXBjryTBgn7O6O20HYg9uVLFcZlNfgH78MnreE/7EH+hjfzn7VyA==",
|
||||||
|
"path": "microsoft.extensions.dependencyinjection/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.dependencyinjection.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-zOIurr59+kUf9vNcsUkCvKWZv+fPosUZXURZesYkJCvl0EzTc9F7maAO4Cd2WEV7ZJJ0AZrFQvuH6Npph9wdBw==",
|
||||||
|
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-a0EWuBs6D3d7XMGroDXm+WsAi5CVVfjOJvyxurzWnuhBN9CO+1qHKcrKV1JK7H/T4ZtHIoVCOX/YyWM8K87qtw==",
|
||||||
|
"path": "microsoft.extensions.logging/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.logging.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-RZkez/JjpnO+MZ6efKkSynN6ZztLpw3WbxNzjLCPBd97wWj1S9ZYPWi0nmT4kWBRa6atHsdM1ydGkUr8GudyDQ==",
|
||||||
|
"path": "microsoft.extensions.logging.abstractions/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.logging.abstractions.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Options/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-1De2LJjmxdqopI5AYC5dIhoZQ79AR5ayywxNF1rXrXFtKQfbQOV9+n/IsZBa7qWlr0MqoGpW8+OY2v/57udZOA==",
|
||||||
|
"path": "microsoft.extensions.options/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.options.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Primitives/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-QmSiO+oLBEooGgB3i0GRXyeYRDHjllqt3k365jwfZlYWhvSHA3UL2NEVV5m8aZa041eIlblo6KMI5txvTMpTwA==",
|
||||||
|
"path": "microsoft.extensions.primitives/10.0.2",
|
||||||
|
"hashPath": "microsoft.extensions.primitives.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Newtonsoft.Json/13.0.4": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==",
|
||||||
|
"path": "newtonsoft.json/13.0.4",
|
||||||
|
"hashPath": "newtonsoft.json.13.0.4.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-9s7VfRmWRp2W/mrBpCxUe8SCDQCWBPgMsdz9gy3Z19ZCfigukBQj5DoluPz1758lzZpnp/ZJ2eN4mhTNfprwUA==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Client/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-jawIdE5meywuxkwy1pQvyxnVhnjYKmZNYH9vWvRo9FTAUIrvtOMMnpsnS9IVBKJ+h+0U7S5R93uWqAOqhHOjrQ==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.client/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.client.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-XLduk2Y05TC1tND6mJON9g1IcX0B9MsxNPbTHM11jyoOgFFoz+GMqh1EoN0uYFHNGRA/hbSFf87nBB6sqm/6nw==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.configuration/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.configuration.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-bHcrfu60PGJWiU4YI2pn0rOpeZCtThHMRGMC9Wv5bP1Fk2zlxTz/QYOxR2Kj17bXmGlu0lUQA1iZDtDUxA1uXg==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.core/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.core.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-O5QD1seSIh6G7wdVbS/FDpVG7T5Ih6zyBDNNFYzA0epfvKeaCOSicVosT+mQXDEqpg4vS6HDCQuJ0q3cB6KC/A==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.gds.client.common/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.gds.client.common.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Gds.Server.Common/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-CWPtco6KEGL/Av3tzgdcTv9QSkmeWwnvwuDG1PgEtP6Qpb9hHk2GteC2NA6AVvE4fgiCpZZl7s+ikeH2koeCLw==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.gds.server.common/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.gds.server.common.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-vS6x1lRJtBgElpPyBZ0/rPfaw3r4gMK4TJwoGAGw4IhQg1rVzv370tIvgNlnfnbReBLs9W7N8FzDstq117Jagw==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.security.certificates/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.security.certificates.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-EprIRVCEcUBoxpUiTG26bImbo9meHEp8Cak4VzkPN3xX9UFZwbZh/rnwu1nmBngsH/QhuBS9QSrsjn0udpJLpw==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.server/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.server.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"OPCFoundation.NetStandard.Opc.Ua.Types/1.5.378.106": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-9WPEMvW7zJSGvfN7vwjXqC9bCoF4WVm+SCk6IAvDz5fLZmnbb37o8mTrHfwsSkDNFWhal6Aszzre8AmNQnW9/g==",
|
||||||
|
"path": "opcfoundation.netstandard.opc.ua.types/1.5.378.106",
|
||||||
|
"hashPath": "opcfoundation.netstandard.opc.ua.types.1.5.378.106.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-ty6kCaqyoh/M/jKV5yojgta+nf7T8zkkjpRI1beLQkrTC+9R6LS1eCEc+3ED2YUlRyA0g0PXExESnxnW3HcVVQ==",
|
||||||
|
"path": "system.collections.immutable/10.0.2",
|
||||||
|
"hashPath": "system.collections.immutable.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Diagnostics.DiagnosticSource/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-lYWBy8fKkJHaRcOuw30d67PrtVjR5754sz5Wl76s8P+vJ9FSThh9b7LIcTSODx1LY7NB3Srvg+JMnzd67qNZOw==",
|
||||||
|
"path": "system.diagnostics.diagnosticsource/10.0.2",
|
||||||
|
"hashPath": "system.diagnostics.diagnosticsource.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Formats.Asn1/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-9Hee6iQ74pDgdRNIL6lO8Vlx2onVWd5aDnqwk4Pvo0h5FklBd7QwcQDKgxeLuhiy0o3ibzUVO0KFQe0/hPXU+Q==",
|
||||||
|
"path": "system.formats.asn1/10.0.2",
|
||||||
|
"hashPath": "system.formats.asn1.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.IO.Pipelines/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-EqMsn9r18ABvTDxrDce4OWDhBE3y+rR23ilG7Y3BudDKrDKrLG/hkD/JmeFZbctAPxSkCjyJ/Ddwbn/g7ufRJA==",
|
||||||
|
"path": "system.io.pipelines/10.0.2",
|
||||||
|
"hashPath": "system.io.pipelines.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Text.Encodings.Web/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-Ro4cLT4qpRy64crfLAy3ekihtXckeXrD5eI6qb6NDSEVyHcHsmH7KgN4dbnIuiBmXIoaCslx4SynLYxag1SLSQ==",
|
||||||
|
"path": "system.text.encodings.web/10.0.2",
|
||||||
|
"hashPath": "system.text.encodings.web.10.0.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Text.Json/10.0.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-zy8ey7I16G9neZ6uzxrnYwS7pidElzN8XarsBjGu7lE2m7afTKMEe18KbY3ZSmh/z/bR40oxjd6hlUcmOEaMHw==",
|
||||||
|
"path": "system.text.json/10.0.2",
|
||||||
|
"hashPath": "system.text.json.10.0.2.nupkg.sha512"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.dll
Normal file
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.dll
Normal file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.pdb
Normal file
BIN
OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.pdb
Normal file
Binary file not shown.
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"runtimeOptions": {
|
||||||
|
"tfm": "net8.0",
|
||||||
|
"framework": {
|
||||||
|
"name": "Microsoft.NETCore.App",
|
||||||
|
"version": "8.0.0"
|
||||||
|
},
|
||||||
|
"configProperties": {
|
||||||
|
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Collections.Immutable.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Collections.Immutable.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Diagnostics.DiagnosticSource.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Diagnostics.DiagnosticSource.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Formats.Asn1.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Formats.Asn1.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/System.IO.Pipelines.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.IO.Pipelines.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Text.Encodings.Web.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Text.Encodings.Web.dll
Executable file
Binary file not shown.
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Text.Json.dll
Executable file
BIN
OpcConnectionTest/bin/Debug/net8.0/System.Text.Json.dll
Executable file
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("OpcConnectionTest")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("OpcConnectionTest")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3181052619700dceeeef81a9a0851130498f177e")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("OpcConnectionTest")]
|
[assembly: System.Reflection.AssemblyProductAttribute("OpcConnectionTest")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("OpcConnectionTest")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("OpcConnectionTest")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
934b875e72b64b90c5572e45c51a754c2d824022123ba85dea23cfc05669d35b
|
c2e941992237f396c84fee88bc09bdecf79f725598c8300136293f3ac50e6b79
|
||||||
|
|||||||
@@ -1,5 +1,39 @@
|
|||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.deps.json
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.runtimeconfig.json
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/OpcConnectionTest.pdb
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/BitFaster.Caching.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Options.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Newtonsoft.Json.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Client.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Configuration.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Core.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Client.Common.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Gds.Server.Common.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Security.Certificates.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Server.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/Opc.Ua.Types.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.Collections.Immutable.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.Diagnostics.DiagnosticSource.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.Formats.Asn1.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.IO.Pipelines.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.Text.Encodings.Web.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/System.Text.Json.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/bin/Debug/net8.0/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll
|
||||||
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.AssemblyReference.cache
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.AssemblyReference.cache
|
||||||
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.GeneratedMSBuildEditorConfig.editorconfig
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.GeneratedMSBuildEditorConfig.editorconfig
|
||||||
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.AssemblyInfoInputs.cache
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.AssemblyInfoInputs.cache
|
||||||
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.AssemblyInfo.cs
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.AssemblyInfo.cs
|
||||||
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.CoreCompileInputs.cache
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.CoreCompileInputs.cache
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.CopyComplete
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/refint/OpcConnectionTest.dll
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.pdb
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.genruntimeconfig.cache
|
||||||
|
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/ref/OpcConnectionTest.dll
|
||||||
|
|||||||
BIN
OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.dll
Normal file
BIN
OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.dll
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
985ad1f23ff5bf15b24f32d665951935d354064a61d300c10a97a85bb842ecaf
|
||||||
BIN
OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.pdb
Normal file
BIN
OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.pdb
Normal file
Binary file not shown.
BIN
OpcConnectionTest/obj/Debug/net8.0/apphost
Executable file
BIN
OpcConnectionTest/obj/Debug/net8.0/apphost
Executable file
Binary file not shown.
BIN
OpcConnectionTest/obj/Debug/net8.0/ref/OpcConnectionTest.dll
Normal file
BIN
OpcConnectionTest/obj/Debug/net8.0/ref/OpcConnectionTest.dll
Normal file
Binary file not shown.
BIN
OpcConnectionTest/obj/Debug/net8.0/refint/OpcConnectionTest.dll
Normal file
BIN
OpcConnectionTest/obj/Debug/net8.0/refint/OpcConnectionTest.dll
Normal file
Binary file not shown.
BIN
OpcConnectionTest/pki/own/certs/OpcTestClient.pfx
Normal file
BIN
OpcConnectionTest/pki/own/certs/OpcTestClient.pfx
Normal file
Binary file not shown.
BIN
OpcConnectionTest/pki/trusted/certs/application_rsa_sha256.der
Executable file
BIN
OpcConnectionTest/pki/trusted/certs/application_rsa_sha256.der
Executable file
Binary file not shown.
BIN
OpcConnectionTest/pki/trusted/certs/rootCA.der
Executable file
BIN
OpcConnectionTest/pki/trusted/certs/rootCA.der
Executable file
Binary file not shown.
1430
OpcConnectionTest/statuscode.json
Normal file
1430
OpcConnectionTest/statuscode.json
Normal file
File diff suppressed because it is too large
Load Diff
30
OpcUaMinimal/OpcUaMinimal.sln
Normal file
30
OpcUaMinimal/OpcUaMinimal.sln
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpcUaMinimal", "OpcUaMinimal.csproj", "{0C38AAFC-1916-357A-13AE-47F9174B60F1}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestService", "TestService\TestService.csproj", "{17DA166F-4680-60B2-477D-380118444B5C}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0C38AAFC-1916-357A-13AE-47F9174B60F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0C38AAFC-1916-357A-13AE-47F9174B60F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0C38AAFC-1916-357A-13AE-47F9174B60F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0C38AAFC-1916-357A-13AE-47F9174B60F1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{17DA166F-4680-60B2-477D-380118444B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{17DA166F-4680-60B2-477D-380118444B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{17DA166F-4680-60B2-477D-380118444B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{17DA166F-4680-60B2-477D-380118444B5C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {996D0811-5A91-4171-B40A-0692BA9BFEFB}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// <autogenerated />
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
[assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute("dotnet-TestService-32e4174a-e341-449d-b4e8-ed95b86df201")]
|
||||||
|
[assembly: System.Reflection.AssemblyCompanyAttribute("TestService")]
|
||||||
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3181052619700dceeeef81a9a0851130498f177e")]
|
||||||
|
[assembly: System.Reflection.AssemblyProductAttribute("TestService")]
|
||||||
|
[assembly: System.Reflection.AssemblyTitleAttribute("TestService")]
|
||||||
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|
||||||
|
// MSBuild WriteCodeFragment 클래스에서 생성되었습니다.
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2a508951ac49d144820195cb52e9872d0988d5c3e9bce16356203f7d2df9d3e9
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
is_global = true
|
||||||
|
build_property.TargetFramework = net8.0
|
||||||
|
build_property.TargetPlatformMinVersion =
|
||||||
|
build_property.UsingMicrosoftNETSdkWeb =
|
||||||
|
build_property.ProjectTypeGuids =
|
||||||
|
build_property.InvariantGlobalization =
|
||||||
|
build_property.PlatformNeutralAssembly =
|
||||||
|
build_property.EnforceExtendedAnalyzerRules =
|
||||||
|
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||||
|
build_property.RootNamespace = TestService
|
||||||
|
build_property.ProjectDir = /home/pacer/projects/OpcUaMinimal/TestService/
|
||||||
|
build_property.EnableComHosting =
|
||||||
|
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// <auto-generated/>
|
||||||
|
global using global::Microsoft.Extensions.Configuration;
|
||||||
|
global using global::Microsoft.Extensions.DependencyInjection;
|
||||||
|
global using global::Microsoft.Extensions.Hosting;
|
||||||
|
global using global::Microsoft.Extensions.Logging;
|
||||||
|
global using global::System;
|
||||||
|
global using global::System.Collections.Generic;
|
||||||
|
global using global::System.IO;
|
||||||
|
global using global::System.Linq;
|
||||||
|
global using global::System.Net.Http;
|
||||||
|
global using global::System.Threading;
|
||||||
|
global using global::System.Threading.Tasks;
|
||||||
Binary file not shown.
Binary file not shown.
@@ -13,10 +13,10 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("OpcUaMinimal")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("OpcUaMinimal")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3181052619700dceeeef81a9a0851130498f177e")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("OpcUaMinimal")]
|
[assembly: System.Reflection.AssemblyProductAttribute("OpcUaMinimal")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("OpcUaMinimal")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("OpcUaMinimal")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|
||||||
// Generated by the MSBuild WriteCodeFragment class.
|
// MSBuild WriteCodeFragment 클래스에서 생성되었습니다.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
a745e6c33a6ca21dfa6cf7051fa0dbadc3b703f8cbec423b33c723d2901630c9
|
a4b50e92c292747ea871d774c25954cdd987abe055be5b9e494c7acb67fa4145
|
||||||
|
|||||||
Reference in New Issue
Block a user