본문으로 건너뛰기

Caffeine.Core API

Caffeine Framework의 핵심 모듈 API 레퍼런스입니다.

개요​

Caffeine.Core는 프레임워크의 핵심 기능을 제공하는 모듈로, 드라이버 개발과 태그 관리를 위한 필수 인터페이스와 클래스를 포함합니다.

네임스페이스: Caffeine.Core
어셈블리: Caffeine.Core.dll
.NET 버전: .NET 10.0


주요 인터페이스​

IDriver​

드라이버 구현을 위한 기본 인터페이스입니다.

네임스페이스: Caffeine.Core.Abstractions

설명​

모든 Caffeine 드라이버는 IDriver 인터페이스를 구현해야 합니다. 이 인터페이스는 장비 연결, 데이터 읽기/쓰기, 태그 관리 등의 핵심 기능을 정의합니다.

주요 메서드​

ConnectAsync()​

장비에 비동기로 연결합니다.

Task<bool> ConnectAsync(CancellationToken cancellationToken = default);

매개변수:

  • cancellationToken (CancellationToken): 작업 취소 토큰

반환값: Task<bool> - 연결 성공 시 true, 실패 시 false

예외:

  • TimeoutException: 연결 시간 초과
  • InvalidOperationException: 이미 연결된 상태

사용 예시:

public class ModbusDriver : IDriver
{
public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
{
try
{
// Modbus TCP 연결
await _client.ConnectAsync("192.168.1.100", 502, cancellationToken);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "연결 실패");
return false;
}
}
}
DisconnectAsync()​

장비 연결을 비동기로 해제합니다.

Task DisconnectAsync();

반환값: Task - 비동기 작업

사용 예시:

public async Task DisconnectAsync()
{
await _client.DisconnectAsync();
_logger.LogInformation("연결 해제 완료");
}
ReadTagAsync()​

지정된 태그의 값을 비동기로 읽습니다.

Task<TagValue?> ReadTagAsync(string tagName, CancellationToken cancellationToken = default);

매개변수:

  • tagName (string): 읽을 태그 이름
  • cancellationToken (CancellationToken): 작업 취소 토큰

반환값: Task<TagValue?> - 태그 값 또는 null (태그가 없는 경우)

사용 예시:

var temperature = await driver.ReadTagAsync("Equipment1.Temperature");
if (temperature != null)
{
Console.WriteLine($"온도: {temperature.Value}°C");
}
WriteTagAsync()​

지정된 태그에 값을 비동기로 씁니다.

Task<bool> WriteTagAsync(string tagName, object value, CancellationToken cancellationToken = default);

매개변수:

  • tagName (string): 쓸 태그 이름
  • value (object): 쓸 값
  • cancellationToken (CancellationToken): 작업 취소 토큰

반환값: Task<bool> - 쓰기 성공 시 true

사용 예시:

bool success = await driver.WriteTagAsync("Equipment1.SetPoint", 75.5);
if (success)
{
Console.WriteLine("설정값 변경 완료");
}

주요 클래스​

TagValue​

태그의 값과 메타데이터를 나타내는 클래스입니다.

네임스페이스: Caffeine.Core.Models

속성​

속성타입설명
TagNamestring태그 이름
Valueobject태그 값
TimestampDateTime값이 읽힌 시각 (UTC)
QualityTagQuality데이터 품질 (Good, Bad, Uncertain)
DataTypeType값의 .NET 타입

생성자​

public TagValue(string tagName, object value, TagQuality quality = TagQuality.Good)

사용 예시:

var tagValue = new TagValue(
tagName: "Equipment1.Temperature",
value: 72.5,
quality: TagQuality.Good
);

Console.WriteLine($"{tagValue.TagName}: {tagValue.Value} at {tagValue.Timestamp}");

TagConfiguration​

태그 설정을 정의하는 클래스입니다.

네임스페이스: Caffeine.Core.Abstractions.Tags

속성​

속성타입설명
TagNamestring태그 이름 (고유 식별자)
DriverIdstring드라이버 ID
Addressstring장비 주소 (예: Modbus 레지스터)
DataTypestring데이터 타입 (Int16, Float, String 등)
ScanRateint스캔 주기 (밀리초)
Enabledbool태그 활성화 여부

사용 예시​

var tagConfig = new TagConfiguration
{
TagName = "Equipment1.Temperature",
DriverId = "ModbusTCP_001",
Address = "40001",
DataType = "Float",
ScanRate = 1000, // 1초마다 읽기
Enabled = true
};

열거형​

NotificationChannel​

알림을 전송할 채널을 나타냅니다.

네임스페이스: Caffeine.Core.Abstractions.Alerting

public enum NotificationChannel
{
Email = 0, // 이메일 알림 (MailKit)
Teams = 1, // Microsoft Teams Webhook
SignalR = 2, // 실시간 SignalR Push
Slack = 3, // Slack Webhook (예약)
Kakao = 4, // 카카오톡 알림 (v2.1.3 추가)
Sms = 5, // SMS 문자 알림 (v2.1.3 추가)
Tts = 6, // TTS 음성 알림 (v2.1.3 추가)
Telegram = 7 // Telegram Bot 알림 (v2.1.3 추가)
}

심각도별 라우팅 정책 (v2.1.3):

심각도활성 채널
CriticalEmail + Teams + SMS + TTS + SignalR
ErrorTeams + Kakao + Telegram + SignalR
Warning / InfoSignalR only

TagQuality​

태그 데이터의 품질을 나타냅니다.

네임스페이스: Caffeine.Core.Models

public enum TagQuality
{
Good = 0, // 정상 데이터
Bad = 1, // 오류 데이터
Uncertain = 2 // 불확실한 데이터
}

사용 예시:

if (tagValue.Quality == TagQuality.Good)
{
// 정상 데이터 처리
ProcessData(tagValue.Value);
}
else
{
_logger.LogWarning($"데이터 품질 불량: {tagValue.Quality}");
}

예제​

기본 드라이버 구현​

using Caffeine.Core.Abstractions;
using Caffeine.Core.Models;

public class MyCustomDriver : IDriver
{
private readonly ILogger<MyCustomDriver> _logger;
private bool _isConnected;

public MyCustomDriver(ILogger<MyCustomDriver> logger)
{
_logger = logger;
}

public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
{
_logger.LogInformation("장비 연결 시작");

// 연결 로직
await Task.Delay(100, cancellationToken);
_isConnected = true;

_logger.LogInformation("장비 연결 완료");
return true;
}

public async Task DisconnectAsync()
{
_logger.LogInformation("장비 연결 해제");
_isConnected = false;
await Task.CompletedTask;
}

public async Task<TagValue?> ReadTagAsync(string tagName, CancellationToken cancellationToken = default)
{
if (!_isConnected)
{
throw new InvalidOperationException("연결되지 않음");
}

// 태그 읽기 로직
var value = await ReadFromEquipmentAsync(tagName, cancellationToken);

return new TagValue(tagName, value, TagQuality.Good);
}

public async Task<bool> WriteTagAsync(string tagName, object value, CancellationToken cancellationToken = default)
{
if (!_isConnected)
{
throw new InvalidOperationException("연결되지 않음");
}

// 태그 쓰기 로직
await WriteToEquipmentAsync(tagName, value, cancellationToken);
return true;
}

private async Task<object> ReadFromEquipmentAsync(string tagName, CancellationToken cancellationToken)
{
// 실제 장비 읽기 구현
await Task.Delay(10, cancellationToken);
return 42.5; // 예시 값
}

private async Task WriteToEquipmentAsync(string tagName, object value, CancellationToken cancellationToken)
{
// 실제 장비 쓰기 구현
await Task.Delay(10, cancellationToken);
}
}

태그 구독 및 처리​

using Caffeine.Core.Models;

public class TagSubscriber
{
private readonly IDriver _driver;
private readonly ILogger<TagSubscriber> _logger;

public TagSubscriber(IDriver driver, ILogger<TagSubscriber> logger)
{
_driver = driver;
_logger = logger;
}

public async Task SubscribeAndProcessAsync(string[] tagNames, CancellationToken cancellationToken)
{
await _driver.ConnectAsync(cancellationToken);

while (!cancellationToken.IsCancellationRequested)
{
foreach (var tagName in tagNames)
{
var tagValue = await _driver.ReadTagAsync(tagName, cancellationToken);

if (tagValue != null && tagValue.Quality == TagQuality.Good)
{
ProcessTagValue(tagValue);
}
}

await Task.Delay(1000, cancellationToken); // 1초 대기
}

await _driver.DisconnectAsync();
}

private void ProcessTagValue(TagValue tagValue)
{
_logger.LogInformation($"태그: {tagValue.TagName}, 값: {tagValue.Value}, 시각: {tagValue.Timestamp}");

// 비즈니스 로직 처리
if (tagValue.Value is double temperature && temperature > 80)
{
_logger.LogWarning($"고온 경고: {temperature}°C");
}
}
}

DI 등록​

AddCaffeine()​

Caffeine.Core의 DataCodec 서비스(3종)를 DI 컨테이너에 등록하는 확장 메서드입니다.

네임스페이스: Caffeine.Core.Extensions

public static IServiceCollection AddCaffeine(
this IServiceCollection services,
Action<CaffeineOptions>? configure = null)

동작:

  • IDataCodec<double>, IDataCodec<short>, IDataCodec<int> Singleton 등록
  • 이미 등록된 서비스는 덮어쓰지 않음 (멱등 보장)
  • CaffeineOptions.UseBigEndianCodecs = true 시 Big-Endian 코덱 자동 선택

코덱 등록 옵션:

옵션등록되는 코덱
UseBigEndianCodecs = false (기본값)LittleEndianDoubleCodec, LittleEndianShortCodec, LittleEndianIntCodec
UseBigEndianCodecs = trueBigEndianDoubleCodec, BigEndianShortCodec, BigEndianIntCodec

사용 예시:

// Program.cs
builder.Services.AddCaffeine(); // Little-Endian (기본값)
builder.Services.AddCaffeine(o => o.UseBigEndianCodecs = true); // Big-Endian

app.Services.UseCaffeine(); // LoggerFactory 연결 (선택 사항)
IClock은 별도 등록 필요

AddCaffeine()은 DataCodec만 등록합니다. IClock 등 인프라 서비스는 포함되지 않으므로, 각 Composition Root(Bridge.Host, Engine 등)에서 별도 등록하세요.

// Bridge.Host Program.cs 예시
builder.Services.AddCaffeine();
builder.Services.AddSingleton<IClock, SystemClock>();

CaffeineOptions​

AddCaffeine() 등록 시 사용하는 옵션 클래스입니다.

속성타입기본값설명
UseBigEndianCodecsboolfalseBig-Endian 코덱 사용 여부

UseCaffeine()​

앱 시작 시 DI 컨테이너의 ILoggerFactory를 LogExtensions에 연결합니다.

public static IServiceProvider UseCaffeine(this IServiceProvider provider)

호출하지 않아도 Codec은 정상 동작하며, 로깅만 NullLogger 폴백으로 유지됩니다.


센싱 추상화​

도메인-불가지론적 센싱 인터페이스입니다. 로보틱스, 농업, 산업 IoT 등 모든 센싱 소스에 적용 가능합니다.

네임스페이스: Caffeine.Core.Abstractions.Sensing

ISensingCapability​

센싱 능력을 나타내는 인터페이스입니다.

public interface ISensingCapability
{
string CapabilityName { get; }
IObservable<TelemetryReading> TelemetryStream { get; }
SensorCategory Category { get; }
}
멤버설명
CapabilityName센싱 능력 이름 (예: "TemperatureSensor")
TelemetryStream실시간 텔레메트리 Rx 스트림
Category센서 분류 (SensorCategory enum)

사용 예시:

public class TemperatureSensor : ISensingCapability
{
public string CapabilityName => "TemperatureSensor";
public IObservable<TelemetryReading> TelemetryStream { get; }
public SensorCategory Category => SensorCategory.Temperature;

// TelemetryStream은 IObservable<T>로만 외부 공개
// 내부 구현은 AsObservable()로 래핑하여 Subject 직접 접근 차단

public void PublishReading(double celsius)
{
// 구현체에서 스트림에 값 발행
// 실제 구현은 인터페이스 뒤에 캡슐화
}
}

TelemetryReading​

텔레메트리 측정값 불변 레코드입니다.

public record TelemetryReading(
string SensorId,
double Value,
string Unit,
DateTimeOffset Timestamp,
SensorQuality Quality);
속성타입설명
SensorIdstring센서 고유 식별자
Valuedouble측정값
Unitstring단위 (예: "°C", "bar")
TimestampDateTimeOffset측정 시각 (UTC)
QualitySensorQuality데이터 품질 등급

SensorQuality​

센서 데이터 품질 등급 열거형입니다.

public enum SensorQuality { Good, Uncertain, Bad, Unknown }

SensorCategory​

센서 분류 표준화 열거형입니다. (v2.0.4에서 EC 등 수산/식물 카테고리 추가)

네임스페이스: Caffeine.Core.Abstractions.Sensing.SensorCategory

public enum SensorCategory
{
Unknown = 0, // default(SensorCategory) 안전값

// 공통 환경
Temperature = 1, // 온도 (°C)
Humidity = 2, // 습도 (%RH)
Pressure = 3, // 기압 (hPa)

// 공기 품질 (10번대)
Ammonia = 10, // 암모니아 (ppm) — 축산
CarbonDioxide = 11, // CO2 (ppm)
Illuminance = 12, // 조도 (lux)

// 수질 (20번대) — AquaFarm
DissolvedOxygen = 20, // 용존 산소 (mg/L)
Ph = 21, // pH
Salinity = 22, // 염분 (ppt)
WaterTemperature = 23, // 수온 (°C)
Turbidity = 24, // 탁도 (NTU)
ElectricalConductivity = 25, // 전기전도도 (mS/cm)

// 토양/식물 (30번대) — GreenFarm
SoilMoisture = 30, // 토양 수분 (%)
SoilTemperature = 31, // 토양 온도 (°C)
LightIntensity = 32, // PAR (μmol/m²/s)

// 전기/기계 (40번대)
Voltage = 40, // 전압 (V)
Current = 41, // 전류 (A)
Weight = 42, // 중량/하중 (kg) — TMR 로드셀
Flow = 43, // 유량 (L/min)

Other = 99
}
번호 범위분류주요 값
0 / 1–3공통 / 기본 환경Unknown(0), Temperature(1), Humidity(2), Pressure(3)
10–12공기 품질Ammonia(10), CarbonDioxide(11), Illuminance(12)
20–25수질 (AquaFarm)DissolvedOxygen(20), Ph(21), Salinity(22), WaterTemperature(23), Turbidity(24), ElectricalConductivity(25)
30–32토양/식물 (GreenFarm)SoilMoisture(30), SoilTemperature(31), LightIntensity(32)
40–43전기/기계Voltage(40), Current(41), Weight(42), Flow(43)
99기타Other

안전 추상화​

도메인-불가지론적 안전 정책 및 모니터링 인터페이스입니다.

네임스페이스: Caffeine.Core.Abstractions.Safety

ISafetyPolicy​

작업 요청에 대해 허용/거부를 판정하는 안전 정책 인터페이스입니다.

public interface ISafetyPolicy
{
string PolicyName { get; }
int Priority { get; }
Task<SafetyEvaluationResult> EvaluateAsync(OperationRequest request, CancellationToken ct = default);
}
멤버설명
PolicyName정책 이름
Priority평가 우선순위 (높을수록 먼저 평가)
EvaluateAsync작업 요청에 대한 안전 평가 수행

ISafetyPolicyEngine​

복수 정책을 조합하여 평가하는 인터페이스입니다.

public interface ISafetyPolicyEngine
{
IReadOnlyList<ISafetyPolicy> Policies { get; }
Task<SafetyEvaluationResult> EvaluateAllAsync(OperationRequest request, CancellationToken ct = default);
}

ISafetyMonitor​

안전 위반 이벤트 Rx 스트림을 제공하는 모니터 인터페이스입니다.

public interface ISafetyMonitor
{
IObservable<SafetyViolation> ViolationStream { get; }
}

안전 관련 값 객체​

타입설명
SafetyLevel안전 수준 (Safe, Caution, Warning, Danger, Critical)
SafetyEvaluationResult안전 평가 결과 (Level, Message, ViolatedPolicies)
OperationRequest작업 실행 요청 (OperationId, DeviceId, OperationType, Parameters)
SafetyViolation안전 정책 위반 정보 (PolicyId, Description, Severity, OccurredAt)

사용 예시:

// ISafetyMonitor 구독
_safetyMonitor.ViolationStream
.Where(v => v.Severity >= SafetyLevel.Warning)
.Subscribe(v => _logger.LogWarning("안전 위반: {PolicyId} — {Description}", v.PolicyId, v.Description));

구역 관리 추상화​

도메인-불가지논적 구역(Zone) 관리 인터페이스입니다. 공장 구역, 농업 구역, 로보틱스 작업 구역 등 모든 도메인에 적용 가능합니다.

네임스페이스: Caffeine.Core.Abstractions.Zones

IZoneManager​

Zone CRUD, 계층 조회, 장치 배치, 상태 집계를 제공하는 11개 메서드 인터페이스입니다.

Zone CRUD (5개 메서드)​

Task<ZoneInfo> CreateZoneAsync(ZoneInfo zone, CancellationToken ct = default);
Task<ZoneInfo?> GetZoneAsync(string zoneId, CancellationToken ct = default);
Task<ZoneInfo> UpdateZoneAsync(ZoneInfo zone, CancellationToken ct = default);
Task<bool> DeleteZoneAsync(string zoneId, CancellationToken ct = default);
Task<IReadOnlyList<ZoneInfo>> ListZonesAsync(CancellationToken ct = default);

계층 조회 (1개 메서드)​

Task<IReadOnlyList<ZoneInfo>> GetChildZonesAsync(string parentZoneId, CancellationToken ct = default);

장치 배치 (4개 메서드)​

Task AssignDeviceAsync(ZoneAssignment assignment, CancellationToken ct = default);
Task<bool> UnassignDeviceAsync(string zoneId, string deviceId, CancellationToken ct = default);
Task<IReadOnlyList<ZoneAssignment>> GetDeviceAssignmentsAsync(string zoneId, CancellationToken ct = default);
Task<IReadOnlyList<ZoneAssignment>> GetZoneAssignmentsByDeviceAsync(string deviceId, CancellationToken ct = default);

상태 집계 (1개 메서드)​

Task<ZoneSummary> GetZoneSummaryAsync(string zoneId, CancellationToken ct = default);

IZoneMonitor​

구역 변경 이벤트 Rx 스트림을 제공하는 인터페이스입니다.

public interface IZoneMonitor
{
IObservable<ZoneEvent> ZoneEventStream { get; }
}

Zone 관련 값 객체​

타입설명
ZoneInfo구역 정보 레코드 (ZoneId, Name, Status, ParentZoneId, Metadata)
ZoneAssignment장치-구역 할당 레코드 (DeviceId, ZoneId, Role)
ZoneSummary구역 상태 집계 레코드 (장치 수, 상태별 분포)
ZoneStatus구역 상태 (Active, Inactive, Maintenance, Warning, Critical)
ZoneEvent구역 변경 이벤트 (ZoneEventType, ZoneId, OccurredAt)
ZoneEventType이벤트 유형 (ZoneCreated, ZoneUpdated, ZoneDeleted, DeviceAssigned, DeviceUnassigned, StatusChanged)

사용 예시:

// 구역 생성 및 장치 배치
var zone = await _zoneManager.CreateZoneAsync(
new ZoneInfo("ZONE-A1", "조립 구역 A1", ZoneStatus.Active));

await _zoneManager.AssignDeviceAsync(
new ZoneAssignment("DEVICE-001", "ZONE-A1", "Primary"));

// 구역 이벤트 스트림 구독
_zoneMonitor.ZoneEventStream
.Where(e => e.EventType == ZoneEventType.StatusChanged)
.Subscribe(e => _logger.LogInformation("구역 상태 변경: {ZoneId}", e.ZoneId));

센서 레지스트리 추상화​

센서 메타데이터의 등록·조회·해제를 담당하는 CRUD 인터페이스입니다. ISensingCapability(런타임 스트림)와 달리 센서의 생명주기 관리를 전담합니다.

네임스페이스: Caffeine.Core.Abstractions.Sensing

v2.1.4 신규 — FIR-027: ISensorRegistry 센서 메타데이터 CRUD

ISensorRegistry​

센서 메타데이터 CRUD 인터페이스입니다. IZoneManager와 대칭되는 설계로, Zone에 속하는 센서의 생명주기를 관리합니다.

public interface ISensorRegistry
{
Task<SensorInfo> RegisterSensorAsync(SensorInfo sensor, CancellationToken ct = default);
Task<SensorInfo?> GetSensorAsync(string sensorId, CancellationToken ct = default);
Task<IReadOnlyList<SensorInfo>> ListSensorsAsync(string? zoneId = null, CancellationToken ct = default);
Task<bool> UnregisterSensorAsync(string sensorId, CancellationToken ct = default);
}
메서드설명
RegisterSensorAsync센서를 등록하고 등록된 SensorInfo를 반환
GetSensorAsyncID로 센서 정보 조회 (없으면 null)
ListSensorsAsync센서 목록 조회 (zoneId 지정 시 해당 Zone 필터)
UnregisterSensorAsync센서 해제 (성공 시 true)

SensorInfo​

센서 메타데이터 불변 레코드입니다.

public record SensorInfo(
string SensorId,
string Name,
SensorCategory Category,
string? ZoneId = null,
string? Unit = null,
IReadOnlyDictionary<string, string>? Metadata = null);
속성타입설명
SensorIdstring센서 고유 식별자
Namestring센서 이름
CategorySensorCategory센서 분류 (SensorCategory enum)
ZoneIdstring?소속 Zone ID (선택)
Unitstring?측정 단위 (예: "°C", "bar")
MetadataIReadOnlyDictionary<string, string>?추가 메타데이터

사용 예시:

// 센서 등록
var sensor = new SensorInfo(
SensorId: "TEMP-A1-001",
Name: "조립구역 A1 온도센서",
Category: SensorCategory.Temperature,
ZoneId: "ZONE-A1",
Unit: "°C");

await _sensorRegistry.RegisterSensorAsync(sensor);

// Zone별 센서 목록 조회
var sensors = await _sensorRegistry.ListSensorsAsync(zoneId: "ZONE-A1");

// 센서 해제
await _sensorRegistry.UnregisterSensorAsync("TEMP-A1-001");

구현체: InMemorySensorRegistry (Caffeine.Infrastructure) — AddCaffeineInfrastructure() 시 Singleton 자동 등록


IDriverCapabilities​

드라이버의 선택적 고급 기능을 조회하기 위한 인터페이스입니다. IDriverModule을 구현하는 드라이버가 선택적으로 추가 구현하여 런타임에 지원 기능을 노출합니다.

네임스페이스: Caffeine.Core.Abstractions.Drivers.IDriverCapabilities

public interface IDriverCapabilities
{
/// <summary>드라이버가 지원하는 통신 프로토콜 목록 (예: "ModbusTCP", "MQTT", "OPC-UA")</summary>
IReadOnlyList<string> SupportedProtocols { get; }

/// <summary>최대 초당 처리 메시지 수 (0 = 무제한)</summary>
int MaxMessagesPerSecond { get; }

/// <summary>오프라인 버퍼링 지원 여부</summary>
bool SupportsOfflineBuffering { get; }

/// <summary>쌍방향 명령/응답 통신 지원 여부</summary>
bool SupportsBidirectional { get; }

/// <summary>드라이버가 읽을 수 있는 센서 카테고리 목록</summary>
IReadOnlyList<string> SupportedSensorCategories { get; }
}
속성타입설명
SupportedProtocolsIReadOnlyList<string>지원 프로토콜 목록 (예: ["ModbusTCP"])
MaxMessagesPerSecondint초당 최대 처리 메시지 수 (0 = 무제한)
SupportsOfflineBufferingbool오프라인 버퍼링 지원 여부
SupportsBidirectionalbool읽기/쓰기 양방향 통신 지원 여부
SupportedSensorCategoriesIReadOnlyList<string>읽을 수 있는 센서 카테고리 이름 목록

사용 예시:

// 드라이버가 IDriverCapabilities를 구현하는지 확인
if (driver is IDriverCapabilities caps)
{
Console.WriteLine($"Protocols: {string.Join(", ", caps.SupportedProtocols)}");
Console.WriteLine($"Max msg/s: {caps.MaxMessagesPerSecond}");
Console.WriteLine($"Bidirectional: {caps.SupportsBidirectional}");
Console.WriteLine($"Sensor categories: {string.Join(", ", caps.SupportedSensorCategories)}");
}

Modbus 드라이버 구현 예시:

// ModbusTcpDriver (Caffeine.Drivers.ModbusTcp)
IReadOnlyList<string> SupportedProtocols => new[] { "ModbusTCP" };
int MaxMessagesPerSecond => 100;
bool SupportsOfflineBuffering => false;
bool SupportsBidirectional => true;

// ModbusRtuDriver (Caffeine.Drivers.ModbusRtu) — 시리얼 대역폭 제한
int MaxMessagesPerSecond => 20;

AAS (Asset Administration Shell) 추상화​

V3에서 추가된 IEC 63278 기반 디지털 트윈 인터페이스입니다.

네임스페이스: Caffeine.Core.Abstractions.AAS

IAasShell​

AAS 컨테이너 인터페이스 — 장비 1대에 대응하는 디지털 트윈 단위입니다.

public interface IAasShell
{
string IdShort { get; }
string? GlobalAssetId { get; }
AssetKind AssetKind { get; }
IReadOnlyList<string> SubmodelIds { get; }
string? TenantId { get; }
}
속성타입설명
IdShortstringAAS 단축 식별자
GlobalAssetIdstring?글로벌 자산 ID (IRI)
AssetKindAssetKind자산 종류 (Instance, Type)
SubmodelIdsIReadOnlyList<string>소속 서브모델 ID 목록
TenantIdstring?멀티테넌트 구분자

ISubmodel​

서브모델 — 특정 관점(Nameplate, TechnicalData 등)의 데이터 구조화 단위입니다.

public interface ISubmodel
{
string IdShort { get; }
string? SemanticId { get; }
string SubmodelType { get; }
IReadOnlyList<ISubmodelElement>? Elements { get; }
}

ISubmodelProvider​

서브모델 빌더 인터페이스 — 장비별 서브모델을 동적으로 구성합니다.

public interface ISubmodelProvider
{
string SubmodelType { get; }
string SemanticId { get; }
Task<ISubmodel> BuildSubmodelAsync(string assetId, CancellationToken ct = default);
Task<string> SerializeAsync(ISubmodel submodel, CancellationToken ct = default);
}

기본 제공 Provider:

ProviderSubmodelTypeSemanticId
NameplateSubmodelProviderNameplateIdtaSemanticIds.DigitalNameplate
TechnicalDataSubmodelProviderTechnicalDataIdtaSemanticIds.TechnicalData
OperationalDataSubmodelProviderOperationalDataIdtaSemanticIds.OperationalData
AlarmConditionSubmodelProviderAlarmConditionIdtaSemanticIds.AlarmCondition
MaintenanceHistorySubmodelProviderMaintenanceHistoryIdtaSemanticIds.MaintenanceHistory
PredictiveMaintenanceSubmodelProviderPredictiveMaintenanceIdtaSemanticIds.PredictiveMaintenance
AiModelNameplateSubmodelProviderAiModelNameplateIdtaSemanticIds.AiModelNameplate

ISemanticIdCatalog​

장비 카테고리별 센서 속성 → SemanticId 자동 매핑 카탈로그입니다.

public interface ISemanticIdCatalog
{
IReadOnlyList<string> GetCategories();
IReadOnlyList<SemanticIdEntry> GetEntries(string category);
string? ResolveSemanticId(string category, string propertyName);
}

지원 카테고리: Pump, Motor, Compressor, HeatExchanger, Conveyor

ISemanticIdMapper​

Caffeine 내부 타입 ↔ SemanticId 양방향 매핑 인터페이스입니다.

public interface ISemanticIdMapper
{
IReadOnlyCollection<string> SupportedTypes { get; }
string? MapToSemanticId(string caffeineType);
string? MapFromSemanticId(string semanticId);
}

사용 예시:

// DI 등록
services.AddCaffeineAas();

// SemanticId 매핑
var mapper = serviceProvider.GetRequiredService<ISemanticIdMapper>();
var irdi = mapper.MapToSemanticId("Temperature");
// → "0173-1#02-AAI835#001" (ECLASS IRDI)

참고 항목​


네임스페이스: Caffeine.Core 어셈블리: Caffeine.Core.dll (v3.0.0) .NET 플랫폼: .NET 10.0