본문으로 건너뛰기

Hands-on Lab: Simulation → AAS → 예측 알림

이 핸즈온 랩에서는 Caffeine V3의 핵심 기능을 단계별로 실습합니다.

개요​

단계주제소요 시간
1시뮬레이션 드라이버로 데이터 수집15분
2AAS(Asset Administration Shell) 매핑20분
3예측 정비 알림 설정15분

사전 요구 사항:

  • .NET 10 SDK
  • Docker Desktop
  • IDE (Visual Studio, Rider, 또는 VS Code)

1단계: 환경 준비​

Docker Compose 실행​

# Caffeine CLI로 docker-compose.yml 생성
cafe docker generate --profile slim

# 인프라 서비스 시작
docker compose up -d

프로젝트 생성​

# 튜토리얼용 프로젝트 클론 또는 생성
dotnet new console -n CaffeineLab
cd CaffeineLab

# Caffeine 패키지 추가
dotnet add package NEXCODE.Caffeine.Core --version 3.0.0
dotnet add package NEXCODE.Caffeine.AAS --version 3.0.0
dotnet add package NEXCODE.Caffeine.Infrastructure --version 3.0.0

2단계: 시뮬레이션 드라이버로 데이터 수집​

드라이버 설정​

using Caffeine.Core.Abstractions.Drivers;
using Caffeine.Core.Domain.Configuration;

// 시뮬레이션 드라이버 설정
var definition = new DriverDefinition
{
Identifier = "SIM-LAB-01",
DriverType = "Simulation",
Options = new Dictionary<string, string>
{
["PollingInterval"] = "1000",
["TagCount"] = "5"
}
};

태그 구독​

using System.Reactive.Linq;

// 드라이버 연결
await driver.ConnectAsync();

// Rx 스트림으로 실시간 데이터 수신
driver.TagStream
.Where(t => t.TagName.Contains("Temperature"))
.Buffer(TimeSpan.FromSeconds(5))
.Subscribe(batch =>
{
var avg = batch.Average(t => (double)t.Value);
Console.WriteLine($"[5초 평균 온도] {avg:F1}°C ({batch.Count}개 샘플)");
});

Console.WriteLine("데이터 수집 중... (Ctrl+C로 종료)");
await Task.Delay(Timeout.Infinite);

실행 결과:

[5초 평균 온도] 72.3°C (5개 샘플)
[5초 평균 온도] 73.1°C (5개 샘플)
[5초 평균 온도] 71.8°C (5개 샘플)

3단계: AAS(Asset Administration Shell) 매핑​

SemanticId 매핑​

using Caffeine.AAS;
using Caffeine.AAS.Mapping;

// 기본 SemanticId 매퍼
var mapper = new DefaultSemanticIdMapper();

// Caffeine 타입 → ECLASS IRDI 변환
var temperatureIrdi = mapper.MapToSemanticId("Temperature");
Console.WriteLine($"Temperature → {temperatureIrdi}");
// 출력: Temperature → 0173-1#02-AAI835#001

// 역방향 변환
var caffeineType = mapper.MapFromSemanticId(IdtaSemanticIds.Pressure);
Console.WriteLine($"{IdtaSemanticIds.Pressure} → {caffeineType}");
// 출력: 0173-1#02-AAE912#007 → Pressure

서브모델 빌드​

using Caffeine.AAS.Domain;
using Caffeine.AAS.Mapping;
using Caffeine.Core.Domain.Configuration;

// 태그를 AAS SubmodelElement로 변환
var tag = new TagDefinition("Temp-001")
{
LogicalName = "Temp-001",
DataType = "Float",
Unit = "Celsius",
SemanticType = "Temperature",
PhysicalMin = 0.0,
PhysicalMax = 150.0
};

var element = TagToAasConverter.ToSubmodelElement(tag, mapper);
Console.WriteLine($"IdShort: {element.IdShort}");
Console.WriteLine($"SemanticId: {element.SemanticId}");
Console.WriteLine($"Unit: {element.Unit}");
// IdShort: Temp-001
// SemanticId: 0173-1#02-AAI835#001
// Unit: Celsius

SemanticId 카탈로그 활용​

using Caffeine.AAS.Catalog;

var catalog = new SemanticIdCatalog();

// 지원 장비 카테고리 확인
var categories = catalog.GetCategories();
Console.WriteLine($"지원 카테고리: {string.Join(", ", categories)}");
// 지원 카테고리: Pump, Motor, Compressor, HeatExchanger, Conveyor

// 펌프 센서 속성 매핑 조회
var pumpEntries = catalog.GetEntries("Pump");
foreach (var entry in pumpEntries)
{
Console.WriteLine($" {entry.PropertyName} → {entry.SemanticId}");
}

4단계: 예측 알림 파이프라인​

이상 감지 + 알림​

using System.Reactive.Linq;

// 온도 이상 감지 파이프라인
driver.TagStream
.Where(t => t.TagName.Contains("Temperature"))
.Select(t => (double)t.Value)
.Buffer(10, 1) // 슬라이딩 윈도우 10개
.Select(window => new
{
Avg = window.Average(),
StdDev = Math.Sqrt(window.Average(v => Math.Pow(v - window.Average(), 2))),
Latest = window.Last()
})
.Where(stats => Math.Abs(stats.Latest - stats.Avg) > 2 * stats.StdDev)
.Throttle(TimeSpan.FromSeconds(30)) // 30초 중복 억제
.Subscribe(anomaly =>
{
Console.WriteLine($"[ANOMALY] 온도 이상 감지!");
Console.WriteLine($" 현재: {anomaly.Latest:F1}°C");
Console.WriteLine($" 평균: {anomaly.Avg:F1}°C (표준편차: {anomaly.StdDev:F2})");
});

5단계: 전체 통합​

DI 구성 (운영 환경)​

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Caffeine Core 등록
builder.Services.AddCaffeine();

// AAS 등록
builder.Services.AddCaffeineAas();

// Infrastructure 등록 (Redis, InfluxDB)
builder.Services.AddCaffeineInfrastructure(builder.Configuration);

var app = builder.Build();
await app.RunAsync();

정리​

# Docker 서비스 중지
docker compose down

# 데이터 볼륨까지 삭제
docker compose down -v

다음 단계​


최종 업데이트: 2026-03-20