본문으로 건너뛰기

Caffeine.Client API

Caffeine Framework 클라이언트 SDK API 레퍼런스입니다.

개요

Caffeine.Client는 Caffeine 플랫폼에 접근하기 위한 클라이언트 SDK로, gRPC, GraphQL, SignalR 등 다양한 프로토콜을 지원합니다.

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


주요 클래스

CaffeineClient

Caffeine 플랫폼에 연결하기 위한 메인 클라이언트 클래스입니다.

네임스페이스: Caffeine.Client

생성자

public CaffeineClient(CaffeineClientOptions options)

매개변수:

  • options (CaffeineClientOptions): 클라이언트 설정

주요 메서드

ConnectAsync()

Caffeine 서버에 비동기로 연결합니다.

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

반환값: Task<bool> - 연결 성공 시 true

사용 예시:

var options = new CaffeineClientOptions
{
ServerUrl = "https://localhost:5001",
ApiKey = "your-api-key"
};

var client = new CaffeineClient(options);
bool connected = await client.ConnectAsync();

if (connected)
{
Console.WriteLine("서버 연결 성공");
}
ReadTagAsync()

태그 값을 비동기로 읽습니다.

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

매개변수:

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

반환값: Task<TagValue?> - 태그 값

사용 예시:

var temperature = await client.ReadTagAsync("Equipment1.Temperature");
if (temperature != null)
{
Console.WriteLine($"현재 온도: {temperature.Value}°C");
}
ReadTagsAsync()

여러 태그를 한 번에 읽습니다.

Task<Dictionary<string, TagValue>> ReadTagsAsync(string[] tagNames, CancellationToken cancellationToken = default);

매개변수:

  • tagNames (string[]): 태그 이름 배열
  • cancellationToken (CancellationToken): 취소 토큰

반환값: Task<Dictionary<string, TagValue>> - 태그 이름과 값의 딕셔너리

사용 예시:

var tagNames = new[] { "Equipment1.Temperature", "Equipment1.Pressure", "Equipment1.Flow" };
var values = await client.ReadTagsAsync(tagNames);

foreach (var (name, value) in values)
{
Console.WriteLine($"{name}: {value.Value}");
}
WriteTagAsync()

태그에 값을 씁니다.

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

매개변수:

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

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

사용 예시:

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

태그 변경 사항을 실시간으로 구독합니다 (SignalR).

Task SubscribeTagAsync(string tagName, Action<TagValue> onTagChanged, CancellationToken cancellationToken = default);

매개변수:

  • tagName (string): 구독할 태그 이름
  • onTagChanged (Action<TagValue>): 태그 변경 시 호출될 콜백
  • cancellationToken (CancellationToken): 취소 토큰

사용 예시:

await client.SubscribeTagAsync("Equipment1.Temperature", (tagValue) =>
{
Console.WriteLine($"온도 변경: {tagValue.Value}°C at {tagValue.Timestamp}");

if (tagValue.Value is double temp && temp > 80)
{
Console.WriteLine("⚠️ 고온 경고!");
}
});
UnsubscribeTagAsync()

태그 구독을 해제합니다.

Task UnsubscribeTagAsync(string tagName);

사용 예시:

await client.UnsubscribeTagAsync("Equipment1.Temperature");
Console.WriteLine("구독 해제 완료");

CaffeineClientOptions

클라이언트 설정 옵션 클래스입니다.

네임스페이스: Caffeine.Client

속성

속성타입기본값설명
ServerUrlstring-Caffeine 서버 URL (필수)
ApiKeystring?nullAPI 키 (인증용)
TimeoutTimeSpan30s요청 타임아웃
RetryCountint3재시도 횟수
UseSignalRbooltrueSignalR 사용 여부
UseGrpcboolfalsegRPC 사용 여부

사용 예시

var options = new CaffeineClientOptions
{
ServerUrl = "https://caffeine.example.com",
ApiKey = "sk_live_abc123xyz",
Timeout = TimeSpan.FromSeconds(60),
RetryCount = 5,
UseSignalR = true
};

var client = new CaffeineClient(options);

프로토콜별 클라이언트

GraphQLClient

GraphQL API를 통해 Caffeine에 접근합니다.

네임스페이스: Caffeine.Client.GraphQL

주요 메서드

QueryAsync()

GraphQL 쿼리를 실행합니다.

Task<TResult> QueryAsync<TResult>(string query, object? variables = null);

사용 예시:

var graphqlClient = new GraphQLClient("https://localhost:5001/graphql");

var query = @"
query GetTags($equipmentId: String!) {
tags(equipmentId: $equipmentId) {
tagName
value
timestamp
}
}
";

var variables = new { equipmentId = "Equipment1" };
var result = await graphqlClient.QueryAsync<TagsResult>(query, variables);

foreach (var tag in result.Tags)
{
Console.WriteLine($"{tag.TagName}: {tag.Value}");
}

SignalRClient

SignalR을 통한 실시간 통신 클라이언트입니다.

네임스페이스: Caffeine.Client.SignalR

주요 메서드

StartAsync()

SignalR 연결을 시작합니다.

Task StartAsync(CancellationToken cancellationToken = default);
On()

서버 이벤트를 수신합니다.

void On<T>(string eventName, Action<T> handler);

사용 예시:

var signalRClient = new SignalRClient("https://localhost:5001/hubs/tags");

// 이벤트 핸들러 등록
signalRClient.On<TagValue>("TagChanged", (tagValue) =>
{
Console.WriteLine($"태그 변경: {tagValue.TagName} = {tagValue.Value}");
});

// 연결 시작
await signalRClient.StartAsync();

// 태그 구독
await signalRClient.InvokeAsync("SubscribeTag", "Equipment1.Temperature");

예제

기본 사용법

using Caffeine.Client;

class Program
{
static async Task Main(string[] args)
{
// 1. 클라이언트 생성
var options = new CaffeineClientOptions
{
ServerUrl = "https://localhost:5001",
ApiKey = "your-api-key"
};

var client = new CaffeineClient(options);

// 2. 연결
await client.ConnectAsync();

// 3. 태그 읽기
var temperature = await client.ReadTagAsync("Equipment1.Temperature");
Console.WriteLine($"온도: {temperature?.Value}");

// 4. 태그 쓰기
await client.WriteTagAsync("Equipment1.SetPoint", 75.0);

// 5. 연결 해제
await client.DisconnectAsync();
}
}

실시간 모니터링

using Caffeine.Client;

public class RealtimeMonitor
{
private readonly CaffeineClient _client;

public RealtimeMonitor(string serverUrl)
{
var options = new CaffeineClientOptions
{
ServerUrl = serverUrl,
UseSignalR = true
};
_client = new CaffeineClient(options);
}

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

// 각 태그 구독
foreach (var tagName in tagNames)
{
await _client.SubscribeTagAsync(tagName, OnTagChanged, cancellationToken);
}

Console.WriteLine($"{tagNames.Length}개 태그 모니터링 시작");

// 취소될 때까지 대기
await Task.Delay(Timeout.Infinite, cancellationToken);
}

private void OnTagChanged(TagValue tagValue)
{
Console.WriteLine($"[{tagValue.Timestamp:HH:mm:ss}] {tagValue.TagName}: {tagValue.Value}");

// 알람 로직
if (tagValue.TagName.Contains("Temperature") && tagValue.Value is double temp)
{
if (temp > 80)
{
Console.WriteLine($"⚠️ 고온 경고: {temp}°C");
}
else if (temp < 10)
{
Console.WriteLine($"⚠️ 저온 경고: {temp}°C");
}
}
}
}

// 사용
var monitor = new RealtimeMonitor("https://localhost:5001");
var tags = new[] { "Equipment1.Temperature", "Equipment1.Pressure" };

using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};

await monitor.StartMonitoringAsync(tags, cts.Token);

배치 데이터 수집

using Caffeine.Client;

public class BatchDataCollector
{
private readonly CaffeineClient _client;
private readonly List<TagValue> _buffer = new();

public BatchDataCollector(CaffeineClient client)
{
_client = client;
}

public async Task CollectDataAsync(string[] tagNames, int intervalMs, int batchSize)
{
while (true)
{
// 모든 태그 읽기
var values = await _client.ReadTagsAsync(tagNames);

foreach (var (name, value) in values)
{
_buffer.Add(value);

// 버퍼가 가득 차면 저장
if (_buffer.Count >= batchSize)
{
await SaveToDatabase(_buffer);
_buffer.Clear();
}
}

await Task.Delay(intervalMs);
}
}

private async Task SaveToDatabase(List<TagValue> data)
{
Console.WriteLine($"{data.Count}개 데이터 저장 중...");
// 데이터베이스 저장 로직
await Task.Delay(100);
Console.WriteLine("저장 완료");
}
}

에러 처리

연결 실패 처리

try
{
await client.ConnectAsync();
}
catch (HttpRequestException ex)
{
Console.WriteLine($"서버 연결 실패: {ex.Message}");
}
catch (TimeoutException ex)
{
Console.WriteLine($"연결 시간 초과: {ex.Message}");
}

재시도 로직

public async Task<TagValue?> ReadTagWithRetryAsync(string tagName, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
return await client.ReadTagAsync(tagName);
}
catch (Exception ex)
{
if (i == maxRetries - 1) throw;

Console.WriteLine($"재시도 {i + 1}/{maxRetries}: {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i))); // 지수 백오프
}
}
return null;
}

참고 항목


네임스페이스: Caffeine.Client
어셈블리: Caffeine.Client.dll (v2.0.6)
.NET 플랫폼: .NET 10.0