본문으로 건너뛰기

AAS API

IEC 63278 Asset Administration Shell REST 및 gRPC API 레퍼런스입니다.

기본 정보​

항목값
Base URL/api/v1
인증JWT 토큰 (모든 엔드포인트 [Authorize] 필수)
Content-Typeapplication/json
버전v1

엔드포인트 요약​

AAS Repository API​

메서드경로설명
GET/api/v1/aasAAS 목록 조회
GET/api/v1/aas/{id}AAS 상세 조회
POST/api/v1/aasAAS 생성
PUT/api/v1/aas/{id}AAS 수정
DELETE/api/v1/aas/{id}AAS 삭제
GET/api/v1/aas/{id}/submodels서브모델 조회

AAS Registry API​

메서드경로설명
GET/api/v1/aas-registry/by-asset/{globalAssetId}Asset ID로 AAS 검색
GET/api/v1/aas-registry/search필터 기반 AAS 검색

ConceptDescription API​

메서드경로설명
GET/api/v1/concept-descriptionsConceptDescription 목록 조회
GET/api/v1/concept-descriptions/{id}ConceptDescription 상세 조회
POST/api/v1/concept-descriptionsConceptDescription 생성
PUT/api/v1/concept-descriptions/{id}ConceptDescription 수정
DELETE/api/v1/concept-descriptions/{id}ConceptDescription 삭제

AAS Repository API​

AAS 목록 조회​

전체 AAS Shell 목록을 페이지네이션으로 조회합니다.

요청

GET /api/v1/aas
파라미터타입필수기본값설명
pageintN1페이지 번호
pageSizeintN20페이지 크기 (최대 100)
assetKindstringN-필터: Instance 또는 Type

curl 예시

curl -X GET "http://localhost:5000/api/v1/aas?page=1&pageSize=10" \
-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",
"specificAssetIds": [
{ "name": "serialNumber", "value": "CVD-2024-001" }
]
},
"submodels": [
{
"type": "ModelReference",
"keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:nameplate:CVD-001" }]
}
]
}
],
"totalCount": 42,
"page": 1,
"pageSize": 10
}

AAS 상세 조회​

특정 AAS Shell의 상세 정보를 조회합니다.

요청

GET /api/v1/aas/{id}
파라미터타입필수설명
idstring (path)YAAS 식별자 (URL 인코딩 필요)

curl 예시

curl -X GET "http://localhost:5000/api/v1/aas/urn%3Acaffeine%3Aaas%3ACVD-001" \
-H "Authorization: Bearer {token}"

응답 (200 OK)

{
"modelType": "AssetAdministrationShell",
"id": "urn:caffeine:aas:CVD-001",
"idShort": "CVD_Equipment_001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-001",
"specificAssetIds": [
{ "name": "serialNumber", "value": "CVD-2024-001" },
{ "name": "manufacturer", "value": "NEXCODE" }
]
},
"submodels": [
{
"type": "ModelReference",
"keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:nameplate:CVD-001" }]
},
{
"type": "ModelReference",
"keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:technical-data:CVD-001" }]
},
{
"type": "ModelReference",
"keys": [{ "type": "Submodel", "value": "urn:caffeine:sm:operational-data:CVD-001" }]
}
]
}

응답 (404 Not Found)

{
"errorCode": "AAS_NOT_FOUND",
"message": "AAS not found: urn:caffeine:aas:CVD-001"
}

AAS 생성​

새 AAS Shell을 생성합니다.

요청

POST /api/v1/aas

요청 본문

{
"idShort": "CVD_Equipment_001",
"id": "urn:caffeine:aas:CVD-001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-001",
"specificAssetIds": [
{ "name": "serialNumber", "value": "CVD-2024-001" }
]
},
"submodels": []
}

curl 예시

curl -X POST http://localhost:5000/api/v1/aas \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"idShort": "CVD_Equipment_001",
"id": "urn:caffeine:aas:CVD-001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-001"
}
}'

응답 (201 Created)

{
"id": "urn:caffeine:aas:CVD-001",
"idShort": "CVD_Equipment_001",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-001"
},
"submodels": []
}

응답 (409 Conflict)

동일한 id를 가진 AAS가 이미 존재할 때 반환됩니다.

{
"errorCode": "AAS_ALREADY_EXISTS",
"message": "AAS already exists: urn:caffeine:aas:CVD-001"
}

AAS 수정​

기존 AAS Shell을 수정합니다.

요청

PUT /api/v1/aas/{id}
파라미터타입필수설명
idstring (path)YAAS 식별자 (URL 인코딩 필요)

curl 예시

curl -X PUT "http://localhost:5000/api/v1/aas/urn%3Acaffeine%3Aaas%3ACVD-001" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"idShort": "CVD_Equipment_001_v2",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-001"
}
}'

응답 (200 OK) -- 수정된 AAS Shell 반환

응답 (404 Not Found) -- 해당 ID의 AAS가 없을 때


AAS 삭제​

AAS Shell을 삭제합니다. 연결된 서브모델은 삭제되지 않습니다.

요청

DELETE /api/v1/aas/{id}
파라미터타입필수설명
idstring (path)YAAS 식별자 (URL 인코딩 필요)

curl 예시

curl -X DELETE "http://localhost:5000/api/v1/aas/urn%3Acaffeine%3Aaas%3ACVD-001" \
-H "Authorization: Bearer {token}"

응답 (204 No Content) -- 성공

응답 (404 Not Found) -- 해당 ID의 AAS가 없을 때


서브모델 조회​

특정 AAS Shell에 연결된 모든 서브모델을 조회합니다.

요청

GET /api/v1/aas/{id}/submodels
파라미터타입필수설명
idstring (path)YAAS 식별자 (URL 인코딩 필요)

curl 예시

curl -X GET "http://localhost:5000/api/v1/aas/urn%3Acaffeine%3Aaas%3ACVD-001/submodels" \
-H "Authorization: Bearer {token}"

응답 (200 OK)

{
"items": [
{
"modelType": "Submodel",
"id": "urn:caffeine:sm:nameplate:CVD-001",
"idShort": "Nameplate",
"semanticId": {
"type": "ExternalReference",
"keys": [{ "type": "GlobalReference", "value": "urn:idta:submodel:nameplate:2.0" }]
},
"submodelElements": [
{
"modelType": "Property",
"idShort": "ManufacturerName",
"valueType": "xs:string",
"value": "NEXCODE"
},
{
"modelType": "Property",
"idShort": "SerialNumber",
"valueType": "xs:string",
"value": "CVD-2024-001"
},
{
"modelType": "Property",
"idShort": "ManufacturerProductDesignation",
"valueType": "xs:string",
"value": "CVD-PRO-3000"
}
]
},
{
"modelType": "Submodel",
"id": "urn:caffeine:sm:technical-data:CVD-001",
"idShort": "TechnicalData",
"semanticId": {
"type": "ExternalReference",
"keys": [{ "type": "GlobalReference", "value": "urn:idta:submodel:technical-data:1.2" }]
},
"submodelElements": [
{
"modelType": "SubmodelElementCollection",
"idShort": "ChamberTemp",
"value": [
{ "modelType": "Property", "idShort": "MaxValue", "valueType": "xs:float", "value": "800" },
{ "modelType": "Property", "idShort": "MinValue", "valueType": "xs:float", "value": "0" },
{ "modelType": "Property", "idShort": "Unit", "valueType": "xs:string", "value": "degC" }
]
}
]
}
]
}

응답 (404 Not Found) -- 해당 ID의 AAS가 없을 때


AAS Registry API​

Asset ID로 AAS 검색​

Global Asset ID로 연결된 AAS를 검색합니다.

요청

GET /api/v1/aas-registry/by-asset/{globalAssetId}
파라미터타입필수설명
globalAssetIdstring (path)YGlobal Asset ID (URL 인코딩 필요)

curl 예시

curl -X GET "http://localhost:5000/api/v1/aas-registry/by-asset/urn%3Acaffeine%3Aasset%3ACVD-001" \
-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"
}
}
]
}

필터 기반 AAS 검색​

다양한 조건으로 AAS를 검색합니다.

요청

GET /api/v1/aas-registry/search
파라미터타입필수기본값설명
idShortstringN-IdShort 부분 일치 검색
assetKindstringN-Instance 또는 Type
submodelTypestringN-특정 서브모델을 포함하는 AAS 검색 (예: Nameplate)
maxResultsintN20최대 결과 수 (최대 100)

curl 예시

# IdShort에 "CVD"가 포함된 AAS 검색
curl -X GET "http://localhost:5000/api/v1/aas-registry/search?idShort=CVD&assetKind=Instance&maxResults=10" \
-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"
}
},
{
"id": "urn:caffeine:aas:CVD-002",
"idShort": "CVD_Equipment_002",
"assetInformation": {
"assetKind": "Instance",
"globalAssetId": "urn:caffeine:asset:CVD-002"
}
}
],
"totalCount": 2
}

ConceptDescription API​

ConceptDescription은 AAS 데이터 항목의 의미를 정의하는 메타데이터입니다.

ConceptDescription 목록 조회​

요청

GET /api/v1/concept-descriptions
파라미터타입필수기본값설명
pageintN1페이지 번호
pageSizeintN20페이지 크기
idShortstringN-IdShort 부분 일치 검색

curl 예시

curl -X GET "http://localhost:5000/api/v1/concept-descriptions?idShort=Temperature" \
-H "Authorization: Bearer {token}"

응답 (200 OK)

{
"items": [
{
"modelType": "ConceptDescription",
"id": "0173-1#02-AAI835#001",
"idShort": "Temperature",
"embeddedDataSpecifications": [
{
"dataSpecificationContent": {
"preferredName": [
{ "language": "en", "text": "Temperature" },
{ "language": "ko", "text": "온도" }
],
"unit": "degC",
"valueFormat": "NR1..5"
}
}
]
}
],
"totalCount": 1
}

ConceptDescription 상세 조회​

요청

GET /api/v1/concept-descriptions/{id}

curl 예시

curl -X GET "http://localhost:5000/api/v1/concept-descriptions/0173-1%2302-AAI835%23001" \
-H "Authorization: Bearer {token}"

응답 (200 OK) -- ConceptDescription 상세 JSON

응답 (404 Not Found) -- 해당 ID의 ConceptDescription이 없을 때


ConceptDescription 생성​

요청

POST /api/v1/concept-descriptions

curl 예시

curl -X POST http://localhost:5000/api/v1/concept-descriptions \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"id": "0173-1#02-CUSTOM001#001",
"idShort": "RFPower",
"embeddedDataSpecifications": [
{
"dataSpecificationContent": {
"preferredName": [
{ "language": "en", "text": "RF Power" },
{ "language": "ko", "text": "RF 출력" }
],
"unit": "W",
"valueFormat": "NR1..5"
}
}
]
}'

응답 (201 Created) -- 생성된 ConceptDescription

응답 (409 Conflict) -- 동일 ID가 이미 존재할 때


ConceptDescription 수정​

요청

PUT /api/v1/concept-descriptions/{id}

응답 (200 OK) -- 수정된 ConceptDescription

응답 (404 Not Found) -- 해당 ID가 없을 때


ConceptDescription 삭제​

요청

DELETE /api/v1/concept-descriptions/{id}

응답 (204 No Content) -- 성공

응답 (404 Not Found) -- 해당 ID가 없을 때


gRPC API​

Caffeine Engine은 AAS 관련 gRPC 서비스도 제공합니다.

AasRepositoryApi​

service AasRepositoryApi {
// AAS Shell CRUD
rpc GetAllShells (GetAllShellsRequest) returns (GetAllShellsResponse);
rpc GetShell (GetShellRequest) returns (GetShellResponse);
rpc CreateShell (CreateShellRequest) returns (CreateShellResponse);
rpc UpdateShell (UpdateShellRequest) returns (UpdateShellResponse);
rpc DeleteShell (DeleteShellRequest) returns (DeleteShellResponse);

// Submodel 조회
rpc GetSubmodels (GetSubmodelsRequest) returns (GetSubmodelsResponse);
rpc GetSubmodel (GetSubmodelRequest) returns (GetSubmodelResponse);
}

AasRegistryApi​

service AasRegistryApi {
// Asset ID로 AAS 검색
rpc GetByAssetId (GetByAssetIdRequest) returns (GetByAssetIdResponse);

// 필터 기반 AAS 검색
rpc Search (AasSearchRequest) returns (AasSearchResponse);
}

gRPC 사용 예시 (C#)​

using Grpc.Net.Client;

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new AasRepositoryApi.AasRepositoryApiClient(channel);

// AAS 목록 조회
var response = await client.GetAllShellsAsync(new GetAllShellsRequest
{
Page = 1,
PageSize = 10
});

foreach (var shell in response.Shells)
{
Console.WriteLine($"{shell.IdShort}: {shell.Id}");
}

// 특정 AAS 조회
var shellResponse = await client.GetShellAsync(new GetShellRequest
{
Id = "urn:caffeine:aas:CVD-001"
});

에러 응답​

모든 API 에러는 일관된 형식으로 반환됩니다.

{
"errorCode": "AAS_NOT_FOUND",
"message": "AAS not found: urn:caffeine:aas:CVD-999"
}

에러 코드​

HTTP 상태에러 코드설명
400INVALID_REQUEST요청 본문 유효성 검증 실패
401UNAUTHORIZED인증 토큰 없음 또는 만료
403FORBIDDEN권한 부족
404AAS_NOT_FOUNDAAS Shell을 찾을 수 없음
404SUBMODEL_NOT_FOUNDSubmodel을 찾을 수 없음
404CONCEPT_DESCRIPTION_NOT_FOUNDConceptDescription을 찾을 수 없음
409AAS_ALREADY_EXISTS동일 ID의 AAS가 이미 존재
409CONCEPT_DESCRIPTION_ALREADY_EXISTS동일 ID의 ConceptDescription이 이미 존재
500INTERNAL_ERROR서버 내부 오류

인증​

모든 AAS API 엔드포인트는 JWT 인증이 필수입니다.

토큰 획득​

curl -X POST http://localhost:5000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}'

토큰 사용​

curl -X GET http://localhost:5000/api/v1/aas \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."


v2.3.0 신규 기능​

FIR-039: NetworkComplianceSubmodelProvider​

네트워크 보안 컴플라이언스 진단 결과를 IEC 63278 서브모델로 제공하는 Provider입니다.

SemanticId: https://admin-shell.io/idta/SM/NetworkCompliance/1/0

DI 등록 후 AAS 서브모델 조회 시 자동으로 포함됩니다.

// DI 등록
services.AddScoped<INetworkComplianceChecker, DefaultNetworkComplianceChecker>();
services.AddScoped<ISubmodelProvider, NetworkComplianceSubmodelProvider>();

등록 후 기존 서브모델 조회 엔드포인트로 확인합니다.

GET /api/v1/aas/{id}/submodels

응답에 submodelType: "NetworkCompliance" 항목이 포함됩니다.

{
"submodels": [
{
"submodelType": "NetworkCompliance",
"semanticId": "https://admin-shell.io/idta/SM/NetworkCompliance/1/0",
"elements": [
{ "idShort": "OverallLevel", "value": "High" }
]
}
]
}

커스텀 컴플라이언스 검사 로직이 필요하면 INetworkComplianceChecker를 구현해 등록하세요.


FIR-040: ITagToSubmodelMapper — equipmentCategory 파라미터​

네임스페이스: Caffeine.AAS.Mapping

v2.3.0에서 Map 메서드에 선택적 equipmentCategory 파라미터가 추가되었습니다.

object? Map(
object tagValue,
string equipmentId,
string semanticId,
string? equipmentCategory = null); // v2.3.0 추가

동일한 semanticId(예: Temperature)라도 장비 카테고리에 따라 다른 매핑 규칙을 적용할 수 있습니다.

// 압축기의 Temperature → 다른 단위/범위 규칙
mapper.Map(tagValue, "eqp-001", "0173-1#02-AAV232#002", "Compressor");

// 포장기의 Temperature → 다른 단위/범위 규칙
mapper.Map(tagValue, "eqp-002", "0173-1#02-AAV232#002", "PackagingMachine");

equipmentCategory를 생략하면 카테고리 비구분 기본 규칙이 적용됩니다 (하위 호환).


관련 문서​