본문으로 건너뛰기

AAS 시작하기

Caffeine Framework에서 IEC 63278 AAS 기능을 활성화하고 사용하는 단계별 가이드입니다.

학습 시간: 약 30분
사전 지식: Caffeine 기본 사용법, .NET 기초


사전 요구사항​

항목최소 버전비고
.NET SDK10.0dotnet --version으로 확인
Caffeine Frameworkv3.0.0+AAS 모듈 포함 버전
Caffeine Engine실행 중AAS API 제공

Step 1: AAS 모듈 활성화​

Caffeine Engine 또는 Admin의 서비스 등록에서 AAS 모듈을 활성화합니다.

// Program.cs
services.AddCaffeineAas()
.AddSubmodelProvider<NameplateSubmodelProvider>()
.AddSubmodelProvider<TechnicalDataSubmodelProvider>()
.AddSubmodelProvider<OperationalDataSubmodelProvider>()
.AddSemanticIdMapper<EclassSemanticIdMapper>()
.WithAasxPackageSupport();

AddCaffeineAas()는 AAS 핵심 서비스(Repository, Serializer, Converter 등)를 일괄 등록합니다. 이후 체이닝으로 서브모델 제공자, SemanticId 매퍼 등을 추가합니다.

팁

AAS 모듈은 선택적(Opt-in)입니다. AddCaffeineAas()를 호출하지 않으면 기존 기능에 전혀 영향을 주지 않습니다.


Step 2: 장비 매니페스트 → AAS 변환​

기존 Caffeine 장비 매니페스트(EquipmentManifest)를 AAS Shell로 변환합니다.

// 매니페스트에서 AAS Shell 생성
var converter = serviceProvider.GetRequiredService<IManifestToAasConverter>();

AssetAdministrationShell shell = await converter.ToAasShellAsync(
manifest,
cancellationToken);

// 결과 확인
Console.WriteLine($"AAS ID: {shell.Id}");
Console.WriteLine($"Asset ID: {shell.AssetInformation.GlobalAssetId}");
Console.WriteLine($"서브모델 수: {shell.Submodels.Count}");

IManifestToAasConverter는 매니페스트의 장비 정보(ID, 제조사, 모델명 등)를 AAS Shell의 AssetInformation으로 매핑하고, 태그 정의를 기반으로 서브모델 참조를 자동 생성합니다.


Step 3: 서브모델 빌드​

ISubmodelProvider를 사용하여 장비의 특정 측면에 대한 서브모델을 빌드합니다.

// 서브모델 제공자 목록 조회
var providers = serviceProvider.GetRequiredService<IEnumerable<ISubmodelProvider>>();

foreach (var provider in providers)
{
if (provider.CanBuild(manifest))
{
Submodel submodel = await provider.BuildSubmodelAsync(
manifest,
cancellationToken);

Console.WriteLine($"서브모델: {submodel.IdShort}");
Console.WriteLine($" 요소 수: {submodel.SubmodelElements.Count}");
}
}

기본 제공 서브모델 제공자​

제공자IdShort빌드 조건
NameplateSubmodelProviderNameplate항상 (장비 기본 정보)
TechnicalDataSubmodelProviderTechnicalData태그 정의에 물리량 정보가 있을 때
OperationalDataSubmodelProviderOperationalData실시간 태그가 있을 때

Step 4: JSON 직렬화​

AAS Shell과 서브모델을 IEC 63278-1 표준 JSON 포맷으로 직렬화합니다.

var serializer = serviceProvider.GetRequiredService<IAasSerializer>();

// AAS Shell → JSON
string shellJson = await serializer.SerializeShellAsync(shell, cancellationToken);

// Submodel → JSON
string submodelJson = await serializer.SerializeSubmodelAsync(submodel, cancellationToken);

// JSON → AAS Shell (역직렬화)
AssetAdministrationShell deserialized = await serializer.DeserializeShellAsync(
shellJson,
cancellationToken);

생성된 JSON은 AASX Server, Eclipse BaSyx, FA3ST 등 다른 AAS 구현체와 호환됩니다.

JSON 출력 예시​

{
"idShort": "CVD_Equipment_001",
"id": "urn:caffeine:aas:cvd-001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:cvd-001"
},
"submodels": [
{ "type": "ModelReference", "keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:nameplate:cvd-001" }] },
{ "type": "ModelReference", "keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:technical:cvd-001" }] }
]
}

Step 5: REST API로 조회​

AAS 모듈이 활성화되면 Caffeine Engine에 AAS REST API가 자동으로 등록됩니다.

AAS 목록 조회​

curl -X GET http://localhost:5000/api/v1/aas \
-H "Authorization: Bearer {token}"

응답 (200 OK):

{
"items": [
{
"id": "urn:caffeine:aas:cvd-001",
"idShort": "CVD_Equipment_001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:cvd-001"
}
}
],
"totalCount": 1
}

AAS 상세 조회​

curl -X GET http://localhost:5000/api/v1/aas/urn:caffeine:aas:cvd-001 \
-H "Authorization: Bearer {token}"

서브모델 조회​

curl -X GET http://localhost:5000/api/v1/aas/urn:caffeine:aas:cvd-001/submodels \
-H "Authorization: Bearer {token}"

응답 (200 OK):

{
"items": [
{
"id": "urn:caffeine:sm:nameplate:cvd-001",
"idShort": "Nameplate",
"semanticId": {
"type": "ExternalReference",
"keys": [{ "type": "GlobalReference", "value": "urn:idta:submodel:nameplate:2.0" }]
},
"submodelElements": [
{ "idShort": "ManufacturerName", "valueType": "xs:string", "value": "NEXCODE" },
{ "idShort": "SerialNumber", "valueType": "xs:string", "value": "CVD-2024-001" }
]
}
]
}

Step 6: AASX 파일 Import/Export​

AASX는 AAS의 패키지 포맷(OPC UA Part 12 기반)으로, Shell, Submodel, 첨부 파일을 하나의 ZIP 파일로 묶어 교환합니다.

Export (내보내기)​

var packageHandler = serviceProvider.GetRequiredService<IAasxPackageHandler>();

await packageHandler.ExportAsync(
shell,
submodels,
outputPath: "/exports/cvd-001.aasx",
cancellationToken);

Import (가져오기)​

var (importedShell, importedSubmodels) = await packageHandler.ImportAsync(
filePath: "/imports/external-equipment.aasx",
cancellationToken);

// 가져온 AAS를 Repository에 저장
var repository = serviceProvider.GetRequiredService<IAasRepository>();
await repository.CreateAsync(importedShell, cancellationToken);
노트

AASX Import 시 외부 시스템의 SemanticId가 Caffeine 내부 태그 타입과 자동 매핑됩니다. 매핑할 수 없는 SemanticId는 원본 그대로 보존됩니다.


Step 7: 태그 ↔ AAS 양방향 변환​

Caffeine의 태그(Tag) 시스템과 AAS SubmodelElement 간 양방향 변환을 지원합니다.

태그 → AAS 변환​

var tagToAas = serviceProvider.GetRequiredService<ITagToAasConverter>();

// 단일 태그 변환
SubmodelElement element = tagToAas.Convert(tagDefinition);
Console.WriteLine($"IdShort: {element.IdShort}");
Console.WriteLine($"SemanticId: {element.SemanticId}");

// 복수 태그 일괄 변환
IReadOnlyList<SubmodelElement> elements = tagToAas.ConvertMany(tagDefinitions);

AAS → 태그 변환​

var aasToTag = serviceProvider.GetRequiredService<IAasToTagConverter>();

// SubmodelElement → TagDefinition
TagDefinition tag = aasToTag.Convert(submodelElement);
Console.WriteLine($"태그명: {tag.Name}");
Console.WriteLine($"타입: {tag.DataType}");

이 양방향 변환을 통해 외부 AAS 시스템에서 가져온 장비 정의를 Caffeine 태그로 자동 등록하거나, Caffeine 태그를 AAS 표준으로 내보낼 수 있습니다.


Step 8: SemanticId 매핑​

SemanticId는 AAS 데이터 항목에 국제 표준 의미를 부여하는 식별자입니다. Caffeine은 태그 타입에서 SemanticId를 자동 결정합니다.

기본 매퍼 사용​

var mapper = serviceProvider.GetRequiredService<ISemanticIdMapper>();

// 태그 타입 → ECLASS IRDI
SemanticId? semanticId = mapper.Map("Temperature");
// 결과: 0173-1#02-AAI835#001

bool canMap = mapper.CanMap("Pressure");
// 결과: true

체이닝 매퍼​

여러 매퍼를 체이닝하여 우선순위 기반으로 매핑할 수 있습니다. 첫 번째 매퍼가 매핑할 수 없으면 다음 매퍼로 폴백합니다.

services.AddCaffeineAas()
.AddSemanticIdMapper<CustomSemanticIdMapper>() // 우선순위 1: 프로젝트 전용
.AddSemanticIdMapper<EclassSemanticIdMapper>(); // 우선순위 2: ECLASS 기본

커스텀 매퍼를 구현하려면 ISemanticIdMapper 인터페이스를 구현합니다.

public class CustomSemanticIdMapper : ISemanticIdMapper
{
public SemanticId? Map(string tagType)
{
return tagType switch
{
"GasFlow_N2" => new SemanticId("0173-1#02-CUSTOM001#001"),
"GasFlow_SiH4" => new SemanticId("0173-1#02-CUSTOM002#001"),
_ => null // 매핑할 수 없으면 null → 다음 매퍼로 폴백
};
}

public bool CanMap(string tagType)
=> tagType is "GasFlow_N2" or "GasFlow_SiH4";
}

Step 9: RAG 파이프라인 활성화 (선택)​

AAS 문서와 장비 매뉴얼을 AI 기반 RAG(Retrieval-Augmented Generation) 파이프라인으로 검색하고 분석할 수 있습니다.

// RAG 파이프라인 추가 등록
services.AddCaffeineAasRag()
.WithDocumentIngestion()
.WithVectorSearch()
.WithLlmIntegration();

RAG가 활성화되면 다음 기능을 사용할 수 있습니다.

  • 문서 인제스트: AAS 서브모델의 Documentation에 첨부된 PDF, 매뉴얼을 벡터 DB에 인덱싱
  • 자연어 검색: "CVD 장비의 최대 허용 온도는?"과 같은 자연어 질의
  • 조치 가이드: 알람 발생 시 관련 매뉴얼에서 조치 방법 자동 추천
주의

RAG 파이프라인은 별도의 벡터 DB 인프라가 필요합니다. 상세 설정은 RAG 가이드를 참조하세요.


전체 구성 예시​

// Program.cs — AAS 전체 기능 활성화
var builder = WebApplication.CreateBuilder(args);

// Caffeine 핵심 서비스 (기존)
builder.Services.AddCaffeineEngine();

// AAS 모듈
builder.Services.AddCaffeineAas()
.AddSubmodelProvider<NameplateSubmodelProvider>()
.AddSubmodelProvider<TechnicalDataSubmodelProvider>()
.AddSubmodelProvider<OperationalDataSubmodelProvider>()
.AddSemanticIdMapper<EclassSemanticIdMapper>()
.WithAasxPackageSupport();

// RAG 파이프라인 (선택)
builder.Services.AddCaffeineAasRag()
.WithDocumentIngestion()
.WithVectorSearch()
.WithLlmIntegration();

var app = builder.Build();
app.MapCaffeineAasEndpoints(); // AAS REST API 엔드포인트 매핑
app.Run();

다음 단계​