OPC DB server Project First Commit

This commit is contained in:
2026-02-09 02:55:47 +00:00
commit 3181052619
53 changed files with 5719 additions and 0 deletions

137
.Notebook/BRIN 설명.md Normal file
View File

@@ -0,0 +1,137 @@
1⃣ BRIN 인덱스란?
Block Range INdex 의 약자
대용량 테이블에서 연속적인 값(순차적/시간적)에 최적화
일반 B-Tree 인덱스보다 작고 빠르게 생성 가능
하지만 랜덤값 검색에는 적합하지 않음
💡 요약:
특징 설명
장점 작은 크기, 빠른 생성, 디스크 절약
단점 랜덤/불규칙 값 검색 느림
사용 예 날짜, 시퀀스, ID 등 순차적 값 컬럼
2⃣ BRIN 인덱스 생성 기본 문법
CREATE INDEX index_name
ON table_name USING brin (column_name);
예제:
CREATE INDEX brin_test_table_age
ON test_table USING brin (age);
test_table의 age 컬럼에 BRIN 인덱스 생성
대량 데이터에서 범위 검색할 때 효율적
3⃣ BRIN 인덱스 옵션
CREATE INDEX brin_test_table_age
ON test_table USING brin (age)
WITH (pages_per_range = 32);
pages_per_range → 한 인덱스 범위에 몇 페이지를 묶을지 설정 (기본값 128)
범위를 작게 하면 검색 정확도 ↑, 인덱스 크기 ↑
범위를 크게 하면 인덱스 작고 빠름, 정확도 ↓
4⃣ 사용 예제
범위 검색
-- age가 30 이상 40 이하인 데이터 검색
SELECT * FROM test_table
WHERE age BETWEEN 30 AND 40;
BRIN 인덱스를 생성하면 범위 검색이 빨라짐
작은 테이블에서는 체감 안 될 수 있음 → 수십만~수백만 행 이상에서 효과적
복합 컬럼 BRIN 인덱스
CREATE INDEX brin_test_table_name_age
ON test_table USING brin (name, age);
여러 컬럼 순서대로 범위 기반 검색 가능
💡 Tip
BRIN 인덱스는 연속적인 값에서 진가
순차적 시퀀스, 타임스탬프 컬럼에 주로 사용
랜덤/고르게 분포된 값 → B-Tree 인덱스가 더 적합
===========================================================================
1⃣ TimescaleDB란?
PostgreSQL 기반 시계열(Time-Series) 데이터베이스 확장
하이퍼테이블(Hypertable) 구조로 자동 파티셔닝
시계열 데이터 삽입, 조회, 집계 최적화
2⃣ BRIN + TimescaleDB의 조합
TimescaleDB는 내부적으로 하이퍼테이블 파티셔닝
시계열 데이터는 시간 컬럼 기준으로 연속적이기 때문에
BRIN 인덱스와 궁합이 매우 좋음
💡 특징:
특징 설명
인덱스 크기 BRIN → 매우 작음
삽입 속도 TimescaleDB → 초당 수십만~수백만 레코드 처리 가능
조회 효율 시간 범위 쿼리 → BRIN + 하이퍼테이블 최적화
3⃣ 기본 사용법
1) TimescaleDB 설치 후 extension 활성화
-- PostgreSQL에서
CREATE EXTENSION IF NOT EXISTS timescaledb;
2) 테이블을 하이퍼테이블로 변환
CREATE TABLE sensor_data (
time TIMESTAMPTZ NOT NULL,
device_id INT NOT NULL,
temperature DOUBLE PRECISION NOT NULL
);
-- 하이퍼테이블로 변환 (시간 컬럼: time)
SELECT create_hypertable('sensor_data', 'time');
3) BRIN 인덱스 생성
-- 시간 기준 BRIN 인덱스
CREATE INDEX brin_sensor_time
ON sensor_data USING brin (time);
-- 필요시 device_id 추가 가능
CREATE INDEX brin_sensor_device_time
ON sensor_data USING brin (device_id, time);
시간 컬럼 순차적 → BRIN 범위 검색에 최적화
작은 인덱스로 수십억 행도 검색 가능
4⃣ 범위 조회 예제
-- 특정 시간 범위 데이터 조회
SELECT *
FROM sensor_data
WHERE time BETWEEN '2026-02-01 00:00:00' AND '2026-02-02 00:00:00';
BRIN 인덱스 덕분에 빠른 범위 스캔 가능
🔹 정리
TimescaleDB = 시계열 최적화 + 자동 파티셔닝
BRIN 인덱스 = 연속적 시간 컬럼에 최적화된 작은 범위 인덱스
조합 = 대용량 시계열 데이터 + 낮은 디스크 사용 + 빠른 범위 쿼리

View File

@@ -0,0 +1,60 @@
1⃣ 프로젝트 폴더에서 NuGet 설치
터미널에서 프로젝트 디렉토리로 이동:
cd ~/projects/DbTest
패키지 설치:
dotnet add package OPCFoundation.NetStandard.Opc.Ua
이 명령어가 NuGet에서 라이브러리 다운로드 + 프로젝트에 추가까지 해줌
설치 후 출력 메시지에 Successfully added 확인
2⃣ 설치 확인
dotnet list package
출력 예시:
Project 'DbTest' has the following package references
[net8.0]:
Top-level Package Requested Resolved
> OPCFoundation.NetStandard.Opc.Ua 1.4.365 1.4.365
3⃣ 테스트 코드
설치 완료 후 간단한 OPC UA 연결 테스트 작성 가능:
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
class Program
{
static async Task Main()
{
var config = new ApplicationConfiguration
{
ApplicationName = "ExperionClient",
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier()
},
ClientConfiguration = new ClientConfiguration()
};
await config.Validate(ApplicationType.Client);
var endpointURL = "opc.tcp://<EXPERION_IP>:4840";
var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, useSecurity: false);
var session = await Session.Create(config,
new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)),
false, "", 60000, null, null);
Console.WriteLine("Experion OPC UA 연결 성공!");
}
}

View File

@@ -0,0 +1,400 @@
Experion 서버 연결 테스트 코드를 작성해드리겠습니다!
🚀 빠른 테스트 프로젝트 생성
bashcd ~/projects
mkdir OpcConnectionTest
cd OpcConnectionTest
# 콘솔 프로젝트 생성
dotnet new console
# .NET 8.0 고정
dotnet new globaljson --sdk-version 8.0.123 --force
# OPC UA 패키지 설치
dotnet add package OPCFoundation.NetStandard.Opc.Ua
dotnet add package OPCFoundation.NetStandard.Opc.Ua.Client
📝 Program.cs
csharpusing Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
namespace OpcConnectionTest
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
// Experion 서버 정보 (VMware 환경)
string primaryEndpoint = "opc.tcp://192.168.xxx.xxx:4840"; // Primary 서버 IP
string secondaryEndpoint = "opc.tcp://192.168.xxx.xxx:4840"; // Secondary 서버 IP (있다면)
Console.WriteLine($"Primary Server: {primaryEndpoint}");
Console.WriteLine($"Secondary Server: {secondaryEndpoint}\n");
try
{
// 1. Application Configuration 생성
var config = new ApplicationConfiguration()
{
ApplicationName = "OPC UA Test Client",
ApplicationType = ApplicationType.Client,
ApplicationUri = "urn:localhost:OpcUaTestClient",
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 },
TraceConfiguration = new TraceConfiguration
{
OutputFilePath = "OpcUaTest.log",
TraceMasks = 0 // 로그 레벨 (0: 없음, 1: Error, 511: 전부)
}
};
await config.Validate(ApplicationType.Client);
// 2. Primary 서버 검색
Console.WriteLine("Step 1: Discovering Primary Server...");
var endpoints = await DiscoverEndpoints(primaryEndpoint);
if (endpoints == null || endpoints.Count == 0)
{
Console.WriteLine("❌ No endpoints found on Primary server!");
return;
}
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
foreach (var ep in endpoints)
{
Console.WriteLine($" - {ep.EndpointUrl} ({ep.SecurityMode})");
}
// 3. Primary 서버 연결
Console.WriteLine("\nStep 2: Connecting to Primary Server...");
var session = await CreateSession(config, endpoints[0]);
if (session == null)
{
Console.WriteLine("❌ Failed to create session!");
return;
}
Console.WriteLine($"✅ Connected! Session ID: {session.SessionId}");
// 4. 서버 정보 읽기
Console.WriteLine("\nStep 3: Reading Server Information...");
await ReadServerInfo(session);
// 5. Redundancy 정보 읽기 (Experion Redundant 확인)
Console.WriteLine("\nStep 4: Checking Redundancy Support...");
await CheckRedundancy(session);
// 6. 샘플 태그 읽기 (있다면)
Console.WriteLine("\nStep 5: Reading Sample Tags...");
await ReadSampleTags(session);
// 7. 연결 종료
Console.WriteLine("\nStep 6: Closing connection...");
session.Close();
Console.WriteLine("✅ Connection closed successfully!");
// Secondary 서버도 테스트 (선택)
if (!string.IsNullOrEmpty(secondaryEndpoint) && secondaryEndpoint != primaryEndpoint)
{
Console.WriteLine("\n\n=== Testing Secondary Server ===");
await TestSecondaryServer(config, secondaryEndpoint);
}
Console.WriteLine("\n✅ All tests completed!");
}
catch (Exception ex)
{
Console.WriteLine($"\n❌ Error: {ex.Message}");
Console.WriteLine($"Stack: {ex.StackTrace}");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
// Endpoint 검색
static async Task<EndpointDescriptionCollection> DiscoverEndpoints(string serverUrl)
{
try
{
var endpointConfiguration = EndpointConfiguration.Create();
endpointConfiguration.OperationTimeout = 10000;
using (var client = DiscoveryClient.Create(new Uri(serverUrl), endpointConfiguration))
{
var endpoints = await client.GetEndpointsAsync(null);
return endpoints;
}
}
catch (Exception ex)
{
Console.WriteLine($"Discovery failed: {ex.Message}");
return null;
}
}
// 세션 생성
static async Task<ISession> CreateSession(ApplicationConfiguration config, EndpointDescription endpoint)
{
try
{
var endpointConfiguration = EndpointConfiguration.Create(config);
var configuredEndpoint = new ConfiguredEndpoint(null, endpoint, endpointConfiguration);
var session = await Session.Create(
config,
configuredEndpoint,
false,
config.ApplicationName,
60000,
new UserIdentity(new AnonymousIdentityToken()), // 익명 인증
null
);
return session;
}
catch (Exception ex)
{
Console.WriteLine($"Session creation failed: {ex.Message}");
return null;
}
}
// 서버 정보 읽기
static async Task ReadServerInfo(ISession session)
{
try
{
// Server Status 노드 읽기
var nodeId = new NodeId(Objects.Server_ServerStatus);
var value = await Task.Run(() => session.ReadValue(nodeId));
Console.WriteLine($"Server Status: {value.Value}");
// Server State 읽기
var stateNodeId = new NodeId(Variables.Server_ServerStatus_State);
var stateValue = await Task.Run(() => session.ReadValue(stateNodeId));
Console.WriteLine($"Server State: {stateValue.Value}");
// Current Time 읽기
var timeNodeId = new NodeId(Variables.Server_ServerStatus_CurrentTime);
var timeValue = await Task.Run(() => session.ReadValue(timeNodeId));
Console.WriteLine($"Server Current Time: {timeValue.Value}");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to read server info: {ex.Message}");
}
}
// Redundancy 지원 확인
static async Task CheckRedundancy(ISession session)
{
try
{
// ServiceLevel 읽기 (Primary: 200+, Secondary: <200)
var serviceLevelNode = new NodeId(Variables.Server_ServiceLevel);
var serviceLevel = await Task.Run(() => session.ReadValue(serviceLevelNode));
byte level = Convert.ToByte(serviceLevel.Value);
Console.WriteLine($"Service Level: {level}");
if (level >= 200)
{
Console.WriteLine("✅ This is PRIMARY server");
}
else if (level > 0)
{
Console.WriteLine("⚠️ This is SECONDARY server");
}
else
{
Console.WriteLine(" Standalone server (no redundancy)");
}
// ServerRedundancy 노드 확인
var redundancyNode = new NodeId(Objects.Server_ServerRedundancy);
var redundancyValue = await Task.Run(() => session.ReadValue(redundancyNode));
Console.WriteLine($"Redundancy Support: {redundancyValue.StatusCode}");
}
catch (Exception ex)
{
Console.WriteLine($"Redundancy check failed: {ex.Message}");
Console.WriteLine(" Server may not support redundancy");
}
}
// 샘플 태그 읽기
static async Task ReadSampleTags(ISession session)
{
try
{
// Browse root folder
var browser = new Browser(session)
{
BrowseDirection = BrowseDirection.Forward,
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
IncludeSubtypes = true,
NodeClassMask = (int)NodeClass.Variable | (int)NodeClass.Object,
ResultMask = (uint)BrowseResultMask.All
};
// Objects 폴더 탐색
var references = browser.Browse(ObjectIds.ObjectsFolder);
Console.WriteLine($"Found {references.Count} nodes in Objects folder:");
int count = 0;
foreach (var reference in references)
{
Console.WriteLine($" - {reference.DisplayName} ({reference.NodeClass})");
if (++count >= 10) // 처음 10개만 표시
{
Console.WriteLine(" ... (more)");
break;
}
}
// 특정 태그가 있다면 읽기 (NodeId를 알고 있을 때)
// var tagNodeId = new NodeId("ns=2;s=YourTagName");
// var tagValue = await Task.Run(() => session.ReadValue(tagNodeId));
// Console.WriteLine($"Tag Value: {tagValue.Value}");
}
catch (Exception ex)
{
Console.WriteLine($"Tag reading failed: {ex.Message}");
}
}
// Secondary 서버 테스트
static async Task TestSecondaryServer(ApplicationConfiguration config, string serverUrl)
{
try
{
var endpoints = await DiscoverEndpoints(serverUrl);
if (endpoints == null || endpoints.Count == 0)
{
Console.WriteLine("❌ Secondary server not reachable");
return;
}
Console.WriteLine($"✅ Secondary server found with {endpoints.Count} endpoint(s)");
var session = await CreateSession(config, endpoints[0]);
if (session != null)
{
Console.WriteLine("✅ Secondary server connection successful!");
// ServiceLevel 확인
var serviceLevelNode = new NodeId(Variables.Server_ServiceLevel);
var serviceLevel = await Task.Run(() => session.ReadValue(serviceLevelNode));
Console.WriteLine($"Secondary Service Level: {serviceLevel.Value}");
session.Close();
}
}
catch (Exception ex)
{
Console.WriteLine($"Secondary test failed: {ex.Message}");
}
}
}
}
⚙️ 설정 수정 포인트
Line 15-16: Experion 서버 IP 주소 변경
csharpstring primaryEndpoint = "opc.tcp://192.168.1.10:4840"; // ← 실제 IP
string secondaryEndpoint = "opc.tcp://192.168.1.11:4840"; // ← 실제 IP
🚀 실행
bashcd ~/projects/OpcConnectionTest
# 빌드
dotnet build
# 실행
dotnet run
```
---
## 📊 예상 출력
```
=== Experion OPC UA Connection Test ===
Primary Server: opc.tcp://192.168.1.10:4840
Secondary Server: opc.tcp://192.168.1.11:4840
Step 1: Discovering Primary Server...
✅ Found 2 endpoint(s)
- opc.tcp://192.168.1.10:4840 (SignAndEncrypt)
- opc.tcp://192.168.1.10:4840 (None)
Step 2: Connecting to Primary Server...
✅ Connected! Session ID: ns=1;i=123456
Step 3: Reading Server Information...
Server State: Running
Server Current Time: 2026-02-08 15:30:45
Step 4: Checking Redundancy Support...
Service Level: 255
✅ This is PRIMARY server
Redundancy Support: Good
Step 5: Reading Sample Tags...
Found 15 nodes in Objects folder:
- Server (Object)
- DeviceSet (Object)
- ...
Step 6: Closing connection...
✅ Connection closed successfully!
✅ All tests completed!
🔧 문제 해결
1. "Connection refused" 에러
bash# 방화벽 확인
sudo ufw status
sudo ufw allow 4840/tcp
# Experion 서버 ping 확인
ping 192.168.1.10
2. "Certificate validation failed"
csharp// Line 25에서 이미 설정됨
AutoAcceptUntrustedCertificates = true
3. IP 주소 확인
bash# VMware에서 Experion 서버 IP 확인
# Windows 개발 PC에서
ping experion-server-name
📝 다음 단계
연결 성공하면:
✅ Tag 목록 가져오기
✅ Tag 구독 (Subscription) 테스트
✅ 실시간 데이터 수신 테스트

View File

@@ -0,0 +1 @@
셧다운 : sudo shutdown now

View File

@@ -0,0 +1,174 @@
현재 설치 상태 요약
✅ 이미 설치된 것들
1. 개발 환경
✓ .NET SDK 8.0.123
✓ .NET SDK 10.0 (aspnetcore-runtime-10.0)
✓ dotnet-sdk-8.0
2. 데이터베이스
✓ PostgreSQL 16.11
✓ TimescaleDB 2.25.0
✓ postgresql-client-16
3. 시스템 도구
✓ Git 2.43.0
✓ curl, wget
✓ vim, nano
✓ htop (시스템 모니터링)
✓ tmux (터미널 멀티플렉서)
🔧 추가로 설치해야 할 것들
1. OPC UA 라이브러리 (NuGet)
bashcd ~/projects/OpcUaMinimal
dotnet add package OPCFoundation.NetStandard.Opc.Ua --version 1.5.374.126
dotnet add package OPCFoundation.NetStandard.Opc.Ua.Client --version 1.5.374.126
또는 더 간단한 라이브러리:
bashdotnet add package Technosoftware.OpcUaNetStandardLibrary --version 7.0.0
2. Entity Framework Core (PostgreSQL)
bashdotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.23
dotnet add package Microsoft.EntityFrameworkCore.Design --version 8.0.23
dotnet add package Microsoft.EntityFrameworkCore.Tools --version 8.0.23
3. SignalR (실시간 통신)
bashdotnet add package Microsoft.AspNetCore.SignalR.Client --version 8.0.23
4. 기타 필수 라이브러리
bash# Logging
dotnet add package Serilog.AspNetCore --version 8.0.3
dotnet add package Serilog.Sinks.File --version 6.0.0
dotnet add package Serilog.Sinks.PostgreSQL --version 3.2.0
# Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Options.ConfigurationExtensions
# Background Service
dotnet add package Microsoft.Extensions.Hosting
dotnet add package Microsoft.Extensions.Hosting.Systemd
5. 시스템 서비스 관련 (Linux에서 필요)
bash# systemd 개발 헤더 (이미 설치됨)
✓ systemd-dev
# 추가 필요한 것
sudo apt update
sudo apt install -y build-essential
📁 프로젝트 구조 생성
bashcd ~/projects
mkdir -p OpcClientSystem
cd OpcClientSystem
# 1. Core 프로젝트
dotnet new classlib -n Domain -o 01_Core/Domain
dotnet new classlib -n Application -o 01_Core/Application
# 2. Infrastructure 프로젝트
dotnet new classlib -n Infrastructure -o 02_Infrastructure
# 3. OPC Client Service
dotnet new worker -n OpcDataCollector.Service -o 03_Service
# 4. Web API
dotnet new webapi -n IndustrialAutomation.API -o 04_WebAPI
# 5. Blazor Web (선택)
dotnet new blazor -n IndustrialAutomation.Web -o 05_Web
# Solution 파일 생성
dotnet new sln -n OpcClientSystem
# 프로젝트들을 Solution에 추가
dotnet sln add 01_Core/Domain/Domain.csproj
dotnet sln add 01_Core/Application/Application.csproj
dotnet sln add 02_Infrastructure/Infrastructure.csproj
dotnet sln add 03_Service/OpcDataCollector.Service/OpcDataCollector.Service.csproj
dotnet sln add 04_WebAPI/IndustrialAutomation.API/IndustrialAutomation.API.csproj
🗄️ PostgreSQL 설정
DB 생성 (아직 안 했다면)
bashsudo -u postgres psql
# PostgreSQL 프롬프트에서
CREATE DATABASE scada;
CREATE USER opcuser WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE scada TO opcuser;
# TimescaleDB 확장 활성화
\c scada
CREATE EXTENSION IF NOT EXISTS timescaledb;
\q
연결 테스트
bashpsql -h localhost -U opcuser -d scada
# 비밀번호 입력 후 연결 확인
🔐 환경 변수 설정
bash# ~/.bashrc 또는 ~/.profile에 추가
echo 'export ConnectionStrings__DefaultConnection="Host=localhost;Database=scada;Username=opcuser;Password=your_password"' >> ~/.bashrc
source ~/.bashrc
🚀 개발 시작 체크리스트
✅ 완료된 것
Ubuntu Server 24.04 설치
PostgreSQL 16 설치
TimescaleDB 설치
.NET SDK 8.0 설치
Git 설치
VSCode Remote SSH 연결
📝 해야 할 것
OPC UA NuGet 패키지 설치
EF Core PostgreSQL 패키지 설치
프로젝트 구조 생성
Database 스키마 생성
OPC Client 기본 연결 테스트
Experion 서버 연결 확인
🎯 다음 단계 제안
bash# 1. 간단한 테스트 프로젝트부터 시작
cd ~/projects
dotnet new console -n OpcTest
cd OpcTest
# 2. OPC UA 패키지 설치
dotnet add package OPCFoundation.NetStandard.Opc.Ua.Client
# 3. Experion 연결 테스트 코드 작성
# (다음 메시지에서 샘플 코드 제공 가능)
# 4. 테스트 실행
dotnet run
필요한 것이 더 있으면 말씀해주세요!
OPC UA 연결 테스트 코드?
DB 스키마 생성 스크립트?
전체 프로젝트 템플릿 코드?
nuget 이미 설치했는데?오전 10:01아! 죄송합니다. NuGet은 .NET SDK에 포함되어 있으니 이미 사용 가능합니다.
제가 말한 건 NuGet 패키지 관리자가 아니라 NuGet 패키지(라이브러리) 설치를 의미한 거였습니다.
정리하면:
✅ 이미 있는 것 (설치 완료)
✓ NuGet (패키지 관리자) - .NET SDK에 포함
✓ .NET SDK 8.0
✓ PostgreSQL 16
✓ TimescaleDB
📦 해야 할 것 (프로젝트에 라이브러리 추가)
프로젝트를 만든 후에:
bashcd ~/projects/OpcUaMinimal # 또는 새 프로젝트 경로
# 이런 명령어들로 라이브러리 추가
dotnet add package OPCFoundation.NetStandard.Opc.Ua.Client
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
NuGet 자체는 설치할 필요 없고,
NuGet을 통해 라이브러리들을 추가하면 됩니다!
🚀 바로 시작할 수 있는 것
bashcd ~/projects/OpcUaMinimal
# OPC UA 라이브러리 추가
dotnet add package OPCFoundation.NetStandard.Opc.Ua.Client
# PostgreSQL 라이브러리 추가
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
# 설치 확인
dotnet list package
이제 Experion 서버 연결 테스트 코드가 필요하신가요?

16
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (Remote)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/DbTest/bin/Debug/net8.0/DbTest.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "integratedTerminal"
}
]
}

15
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"sqltools.connections": [
{
"ssh": "Disabled",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "dbsvr",
"database": "postgres",
"username": "postgres",
"password": "postgres"
}
]
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.5.378.106" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.5.378.106" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,191 @@
// cd ~/projects/OpcConnectionTest
// 기존 파일 삭제
// rm Program.cs
// # 새 파일 생성
//cat > Program.cs << 'EOF'
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
namespace OpcConnectionTest
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("=== Experion OPC UA Connection Test ===\n");
// ⚠️ Experion 서버 IP 주소 수정
string primaryEndpoint = "opc.tcp://192.168.0.20:4840";
string secondaryEndpoint = "opc.tcp://192.168.1.20:4840";
Console.WriteLine($"Primary: {primaryEndpoint}");
Console.WriteLine($"Secondary: {secondaryEndpoint}\n");
ISession? session = null;
try
{
var config = new ApplicationConfiguration()
{
ApplicationName = "OPC Test",
ApplicationType = ApplicationType.Client,
ApplicationUri = "urn:OpcTest",
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("Step 1: Discovering endpoints...");
var endpoints = await DiscoverAsync(config, primaryEndpoint);
if (endpoints.Count == 0)
{
Console.WriteLine("❌ No endpoints found!");
return;
}
Console.WriteLine($"✅ Found {endpoints.Count} endpoint(s)");
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)
{
Console.WriteLine($"\n❌ Error: {ex.Message}");
}
finally
{
if (session != null)
{
await session.CloseAsync();
session.Dispose();
}
}
Console.WriteLine("\nPress Enter to exit...");
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}");
}
}
}
}

View File

@@ -0,0 +1,5 @@
{
"sdk": {
"version": "8.0.123"
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <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: System.Reflection.AssemblyCompanyAttribute("OpcConnectionTest")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("OpcConnectionTest")]
[assembly: System.Reflection.AssemblyTitleAttribute("OpcConnectionTest")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@@ -0,0 +1 @@
934b875e72b64b90c5572e45c51a754c2d824022123ba85dea23cfc05669d35b

View File

@@ -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 = OpcConnectionTest
build_property.ProjectDir = /home/pacer/projects/OpcConnectionTest/
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =

View File

@@ -0,0 +1,8 @@
// <auto-generated/>
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;

View File

@@ -0,0 +1 @@
859302d0d0eef299017c6ba5eb484ad68daade90e3fd76bac845760289b34007

View File

@@ -0,0 +1,5 @@
/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.AssemblyInfoInputs.cache
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.AssemblyInfo.cs
/home/pacer/projects/OpcConnectionTest/obj/Debug/net8.0/OpcConnectionTest.csproj.CoreCompileInputs.cache

View File

@@ -0,0 +1,71 @@
{
"format": 1,
"restore": {
"/home/pacer/projects/OpcConnectionTest/OpcConnectionTest.csproj": {}
},
"projects": {
"/home/pacer/projects/OpcConnectionTest/OpcConnectionTest.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/home/pacer/projects/OpcConnectionTest/OpcConnectionTest.csproj",
"projectName": "OpcConnectionTest",
"projectPath": "/home/pacer/projects/OpcConnectionTest/OpcConnectionTest.csproj",
"packagesPath": "/home/pacer/.nuget/packages/",
"outputPath": "/home/pacer/projects/OpcConnectionTest/obj/",
"projectStyle": "PackageReference",
"configFilePaths": [
"/home/pacer/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"OPCFoundation.NetStandard.Opc.Ua": {
"target": "Package",
"version": "[1.5.378.106, )"
},
"OPCFoundation.NetStandard.Opc.Ua.Client": {
"target": "Package",
"version": "[1.5.378.106, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "/usr/lib/dotnet/sdk/8.0.123/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.8.1</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="/home/pacer/.nuget/packages/" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json/10.0.2/buildTransitive/net8.0/System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json/10.0.2/buildTransitive/net8.0/System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Options.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
{
"version": 2,
"dgSpecHash": "KrguJvkD41Un9qS/sxFwULOR3owX1Gzwg9Kz5TmdqikJypnpz2UYGOX4knjW3w4fcsh2k1y/V+pMLyI7ALdxig==",
"success": true,
"projectFilePath": "/home/pacer/projects/OpcConnectionTest/OpcConnectionTest.csproj",
"expectedPackageFiles": [
"/home/pacer/.nuget/packages/bitfaster.caching/2.5.4/bitfaster.caching.2.5.4.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection/10.0.2/microsoft.extensions.dependencyinjection.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/10.0.2/microsoft.extensions.dependencyinjection.abstractions.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging/10.0.2/microsoft.extensions.logging.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.abstractions/10.0.2/microsoft.extensions.logging.abstractions.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.options/10.0.2/microsoft.extensions.options.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.primitives/10.0.2/microsoft.extensions.primitives.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/newtonsoft.json/13.0.4/newtonsoft.json.13.0.4.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua/1.5.378.106/opcfoundation.netstandard.opc.ua.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.client/1.5.378.106/opcfoundation.netstandard.opc.ua.client.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.configuration/1.5.378.106/opcfoundation.netstandard.opc.ua.configuration.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.core/1.5.378.106/opcfoundation.netstandard.opc.ua.core.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.gds.client.common/1.5.378.106/opcfoundation.netstandard.opc.ua.gds.client.common.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.gds.server.common/1.5.378.106/opcfoundation.netstandard.opc.ua.gds.server.common.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.security.certificates/1.5.378.106/opcfoundation.netstandard.opc.ua.security.certificates.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.server/1.5.378.106/opcfoundation.netstandard.opc.ua.server.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.types/1.5.378.106/opcfoundation.netstandard.opc.ua.types.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/system.collections.immutable/10.0.2/system.collections.immutable.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.diagnostics.diagnosticsource/10.0.2/system.diagnostics.diagnosticsource.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.formats.asn1/10.0.2/system.formats.asn1.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.io.pipelines/10.0.2/system.io.pipelines.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.text.encodings.web/10.0.2/system.text.encodings.web.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.text.json/10.0.2/system.text.json.10.0.2.nupkg.sha512"
],
"logs": []
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.5.378.106" />
</ItemGroup>
</Project>

68
OpcUaMinimal/Program.cs Normal file
View File

@@ -0,0 +1,68 @@
using System;
using System.Threading.Tasks;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
class Program
{
static async Task Main()
{
try
{
// 1⃣ Application 설정
var config = new ApplicationConfiguration
{
ApplicationName = "OpcUaMinimalClient",
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true, // 테스트용
RejectSHA1SignedCertificates = false
},
TransportQuotas = new TransportQuotas
{
OperationTimeout = 15000
},
ClientConfiguration = new ClientConfiguration
{
DefaultSessionTimeout = 60000
}
};
await config.Validate(ApplicationType.Client);
// 2⃣ Endpoint 설정
var endpointUrl = "opc.tcp://192.168.0.20:4840"; // Experion 서버
var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl, useSecurity: true);
var endpoint = new ConfiguredEndpoint(null, selectedEndpoint);
// 3⃣ Session 생성
var userIdentity = new UserIdentity("mngr", "mngr");
var session = await Session.Create(
config,
endpoint,
false,
"MinimalClientSession",
60000,
userIdentity,
null
);
Console.WriteLine("✅ OPC UA 서버 연결 성공!");
// 4⃣ Node 읽기 (예제 NodeId)
var nodeId = new NodeId("ns=1;s=shinam:p-6102.hzset.fieldvalue");
DataValue value = session.ReadValue(nodeId);
Console.WriteLine($"Node Value: {value.Value}");
// 5⃣ 세션 종료
session.Close();
Console.WriteLine("세션 종료");
}
catch (Exception ex)
{
Console.WriteLine($"❌ 오류: {ex.Message}");
}
}
}

View File

@@ -0,0 +1,7 @@
using TestService;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run();

View File

@@ -0,0 +1,12 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"TestService": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-TestService-32e4174a-e341-449d-b4e8-ed95b86df201</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
namespace TestService;
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
}
await Task.Delay(1000, stoppingToken);
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@@ -0,0 +1,67 @@
{
"format": 1,
"restore": {
"/home/pacer/projects/OpcUaMinimal/TestService/TestService.csproj": {}
},
"projects": {
"/home/pacer/projects/OpcUaMinimal/TestService/TestService.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/home/pacer/projects/OpcUaMinimal/TestService/TestService.csproj",
"projectName": "TestService",
"projectPath": "/home/pacer/projects/OpcUaMinimal/TestService/TestService.csproj",
"packagesPath": "/home/pacer/.nuget/packages/",
"outputPath": "/home/pacer/projects/OpcUaMinimal/TestService/obj/",
"projectStyle": "PackageReference",
"configFilePaths": [
"/home/pacer/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"Microsoft.Extensions.Hosting": {
"target": "Package",
"version": "[8.0.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "/usr/lib/dotnet/sdk/8.0.123/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.8.1</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="/home/pacer/.nuget/packages/" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets/8.0.1/buildTransitive/net6.0/Microsoft.Extensions.Configuration.UserSecrets.props" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets/8.0.1/buildTransitive/net6.0/Microsoft.Extensions.Configuration.UserSecrets.props')" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options/8.0.2/buildTransitive/net6.0/Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options/8.0.2/buildTransitive/net6.0/Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder/8.0.2/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder/8.0.2/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/8.0.2/buildTransitive/net6.0/Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/8.0.2/buildTransitive/net6.0/Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets/8.0.1/buildTransitive/net6.0/Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets/8.0.1/buildTransitive/net6.0/Microsoft.Extensions.Configuration.UserSecrets.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
{
"version": 2,
"dgSpecHash": "ZWQ21HZ+POqTdCWO4g+P6098SrAjfL+VZwp4ubdL0W4WcjcrOYY9D3mTiKpjwv2I1u/8M1jpFjbka3A66hh4lw==",
"success": true,
"projectFilePath": "/home/pacer/projects/OpcUaMinimal/TestService/TestService.csproj",
"expectedPackageFiles": [
"/home/pacer/.nuget/packages/microsoft.extensions.configuration/8.0.0/microsoft.extensions.configuration.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.abstractions/8.0.0/microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.binder/8.0.2/microsoft.extensions.configuration.binder.8.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.commandline/8.0.0/microsoft.extensions.configuration.commandline.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.environmentvariables/8.0.0/microsoft.extensions.configuration.environmentvariables.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.fileextensions/8.0.1/microsoft.extensions.configuration.fileextensions.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.json/8.0.1/microsoft.extensions.configuration.json.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.configuration.usersecrets/8.0.1/microsoft.extensions.configuration.usersecrets.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection/8.0.1/microsoft.extensions.dependencyinjection.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/8.0.2/microsoft.extensions.dependencyinjection.abstractions.8.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.diagnostics/8.0.1/microsoft.extensions.diagnostics.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.diagnostics.abstractions/8.0.1/microsoft.extensions.diagnostics.abstractions.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.fileproviders.abstractions/8.0.0/microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.fileproviders.physical/8.0.0/microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.filesystemglobbing/8.0.0/microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.hosting/8.0.1/microsoft.extensions.hosting.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.hosting.abstractions/8.0.1/microsoft.extensions.hosting.abstractions.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging/8.0.1/microsoft.extensions.logging.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.abstractions/8.0.2/microsoft.extensions.logging.abstractions.8.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.configuration/8.0.1/microsoft.extensions.logging.configuration.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.console/8.0.1/microsoft.extensions.logging.console.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.debug/8.0.1/microsoft.extensions.logging.debug.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.eventlog/8.0.1/microsoft.extensions.logging.eventlog.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.eventsource/8.0.1/microsoft.extensions.logging.eventsource.8.0.1.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.options/8.0.2/microsoft.extensions.options.8.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.options.configurationextensions/8.0.0/microsoft.extensions.options.configurationextensions.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.primitives/8.0.0/microsoft.extensions.primitives.8.0.0.nupkg.sha512",
"/home/pacer/.nuget/packages/system.diagnostics.eventlog/8.0.1/system.diagnostics.eventlog.8.0.1.nupkg.sha512"
],
"logs": []
}

5
OpcUaMinimal/global.json Normal file
View File

@@ -0,0 +1,5 @@
{
"sdk": {
"version": "8.0.123"
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <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: System.Reflection.AssemblyCompanyAttribute("OpcUaMinimal")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("OpcUaMinimal")]
[assembly: System.Reflection.AssemblyTitleAttribute("OpcUaMinimal")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@@ -0,0 +1 @@
a745e6c33a6ca21dfa6cf7051fa0dbadc3b703f8cbec423b33c723d2901630c9

View File

@@ -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 = OpcUaMinimal
build_property.ProjectDir = /home/pacer/projects/OpcUaMinimal/
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =

View File

@@ -0,0 +1,8 @@
// <auto-generated/>
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;

View File

@@ -0,0 +1 @@
c2665c134369febb92699f9c637dee81bfc7cc4496d57ce2cf77c31a46183ed0

View File

@@ -0,0 +1,5 @@
/home/pacer/projects/OpcUaMinimal/obj/Debug/net8.0/OpcUaMinimal.csproj.AssemblyReference.cache
/home/pacer/projects/OpcUaMinimal/obj/Debug/net8.0/OpcUaMinimal.GeneratedMSBuildEditorConfig.editorconfig
/home/pacer/projects/OpcUaMinimal/obj/Debug/net8.0/OpcUaMinimal.AssemblyInfoInputs.cache
/home/pacer/projects/OpcUaMinimal/obj/Debug/net8.0/OpcUaMinimal.AssemblyInfo.cs
/home/pacer/projects/OpcUaMinimal/obj/Debug/net8.0/OpcUaMinimal.csproj.CoreCompileInputs.cache

View File

@@ -0,0 +1,67 @@
{
"format": 1,
"restore": {
"/home/pacer/projects/OpcUaMinimal/OpcUaMinimal.csproj": {}
},
"projects": {
"/home/pacer/projects/OpcUaMinimal/OpcUaMinimal.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/home/pacer/projects/OpcUaMinimal/OpcUaMinimal.csproj",
"projectName": "OpcUaMinimal",
"projectPath": "/home/pacer/projects/OpcUaMinimal/OpcUaMinimal.csproj",
"packagesPath": "/home/pacer/.nuget/packages/",
"outputPath": "/home/pacer/projects/OpcUaMinimal/obj/",
"projectStyle": "PackageReference",
"configFilePaths": [
"/home/pacer/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"OPCFoundation.NetStandard.Opc.Ua": {
"target": "Package",
"version": "[1.5.378.106, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "/usr/lib/dotnet/sdk/8.0.123/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/home/pacer/.nuget/packages/</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.8.1</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="/home/pacer/.nuget/packages/" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json/10.0.2/buildTransitive/net8.0/System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json/10.0.2/buildTransitive/net8.0/System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options/10.0.2/buildTransitive/net8.0/Microsoft.Extensions.Options.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
{
"version": 2,
"dgSpecHash": "HWo6QlR3m5TfXqI0ijUJ+5JDkxKB78ILczeTnl0obOg0WccZLjyNL7FVZIrQ/M4TC639cOomKKrMZCcKMatB2A==",
"success": true,
"projectFilePath": "/home/pacer/projects/OpcUaMinimal/OpcUaMinimal.csproj",
"expectedPackageFiles": [
"/home/pacer/.nuget/packages/bitfaster.caching/2.5.4/bitfaster.caching.2.5.4.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection/10.0.2/microsoft.extensions.dependencyinjection.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/10.0.2/microsoft.extensions.dependencyinjection.abstractions.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging/10.0.2/microsoft.extensions.logging.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.logging.abstractions/10.0.2/microsoft.extensions.logging.abstractions.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.options/10.0.2/microsoft.extensions.options.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/microsoft.extensions.primitives/10.0.2/microsoft.extensions.primitives.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/newtonsoft.json/13.0.4/newtonsoft.json.13.0.4.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua/1.5.378.106/opcfoundation.netstandard.opc.ua.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.client/1.5.378.106/opcfoundation.netstandard.opc.ua.client.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.configuration/1.5.378.106/opcfoundation.netstandard.opc.ua.configuration.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.core/1.5.378.106/opcfoundation.netstandard.opc.ua.core.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.gds.client.common/1.5.378.106/opcfoundation.netstandard.opc.ua.gds.client.common.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.gds.server.common/1.5.378.106/opcfoundation.netstandard.opc.ua.gds.server.common.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.security.certificates/1.5.378.106/opcfoundation.netstandard.opc.ua.security.certificates.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.server/1.5.378.106/opcfoundation.netstandard.opc.ua.server.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/opcfoundation.netstandard.opc.ua.types/1.5.378.106/opcfoundation.netstandard.opc.ua.types.1.5.378.106.nupkg.sha512",
"/home/pacer/.nuget/packages/system.collections.immutable/10.0.2/system.collections.immutable.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.diagnostics.diagnosticsource/10.0.2/system.diagnostics.diagnosticsource.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.formats.asn1/10.0.2/system.formats.asn1.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.io.pipelines/10.0.2/system.io.pipelines.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.text.encodings.web/10.0.2/system.text.encodings.web.10.0.2.nupkg.sha512",
"/home/pacer/.nuget/packages/system.text.json/10.0.2/system.text.json.10.0.2.nupkg.sha512"
],
"logs": []
}

24
projects.sln Normal file
View 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}") = "DbTest", "DbTest\DbTest.csproj", "{415DFA00-450B-897D-A776-6D5CCFDA841B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{415DFA00-450B-897D-A776-6D5CCFDA841B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{415DFA00-450B-897D-A776-6D5CCFDA841B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{415DFA00-450B-897D-A776-6D5CCFDA841B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{415DFA00-450B-897D-A776-6D5CCFDA841B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A78BEBC4-47EE-4F8C-93B7-3AFD72593A85}
EndGlobalSection
EndGlobal