본문으로 건너뛰기

Robotics Device API

로봇 장비 프로비저닝, 조회, 명령 실행을 위한 REST API 엔드포인트입니다.

개요

Robotics Device API는 제조 현장의 로봇 및 자동화 장비를 중앙에서 관리하고 제어하는 기능을 제공합니다.

Base URL: /api/v1/devices

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


인증

모든 엔드포인트는 JWT Bearer 토큰 인증이 필요합니다.

Authorization: Bearer <token>

엔드포인트 요약

메서드경로설명
GET/api/v1/devices전체 장비 목록 조회
GET/api/v1/devices/{id}특정 장비 상세 조회
POST/api/v1/devices신규 장비 프로비저닝
POST/api/v1/devices/{id}/commands장비 명령 실행

상세 엔드포인트

GET /api/v1/devices

등록된 전체 장비 목록을 조회합니다.

요청:

GET /api/v1/devices
Authorization: Bearer <token>

응답 (200 OK):

[
{
"deviceId": "robot-arm-001",
"tenantId": "factory-a",
"name": "로봇 팔 #1",
"currentState": "Idle",
"lastSeen": "2026-02-17T10:30:00Z"
},
{
"deviceId": "agv-002",
"tenantId": "factory-a",
"name": "AGV #2",
"currentState": "Working",
"lastSeen": "2026-02-17T10:35:00Z"
}
]

응답 필드:

필드타입설명
deviceIdstring장비 고유 식별자
tenantIdstring?테넌트 ID (멀티테넌시 환경)
namestring장비 이름
currentStatestring현재 상태 (DeviceState 열거형)
lastSeenstring마지막 통신 시각 (ISO 8601, UTC)

DeviceState 값:

  • Unknown — 알 수 없음
  • Provisioned — 프로비저닝됨
  • Offline — 오프라인
  • Online — 온라인
  • Idle — 유휴
  • Working — 작업 중
  • Error — 오류
  • Maintenance — 유지보수
  • Decommissioned — 폐기됨

GET /api/v1/devices/{id}

특정 장비의 상세 정보를 조회합니다.

요청:

GET /api/v1/devices/robot-arm-001
Authorization: Bearer <token>

응답 (200 OK):

{
"deviceId": "robot-arm-001",
"tenantId": "factory-a",
"name": "로봇 팔 #1",
"currentState": "Idle",
"lastSeen": "2026-02-17T10:30:00Z"
}

응답 (404 Not Found):

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404
}

POST /api/v1/devices

신규 장비를 프로비저닝합니다.

요청:

POST /api/v1/devices
Authorization: Bearer <token>
Content-Type: application/json

{
"deviceId": "agv-003",
"name": "AGV #3",
"description": "Warehouse autonomous vehicle"
}

요청 필드:

필드타입필수설명
deviceIdstring장비 고유 식별자
namestring장비 이름
descriptionstring?장비 설명

응답 (201 Created):

{
"deviceId": "agv-003",
"tenantId": null,
"name": "AGV #3",
"currentState": "Offline",
"lastSeen": "2026-02-17T10:40:00Z"
}

응답 헤더:

Location: /api/v1/devices/agv-003

POST /api/v1/devices/{id}/commands

장비에 명령을 전송하여 실행합니다. 명령 실행 전에 Safety Policy Engine을 통해 안전성 검증이 수행됩니다.

요청:

POST /api/v1/devices/robot-arm-001/commands
Authorization: Bearer <token>
Content-Type: application/json

{
"commandId": "cmd-12345",
"deviceId": "robot-arm-001",
"commandType": "MoveTo",
"parameters": {
"x": 100,
"y": 200,
"z": 50,
"speed": 0.5
},
"priority": 1,
"timestamp": "2026-02-17T10:45:00Z"
}

요청 필드:

필드타입필수설명
commandIdstring명령 고유 식별자
deviceIdstring대상 장비 ID (경로 파라미터와 일치해야 함)
commandTypestring명령 유형 (예: MoveTo, PickUp, Release)
parametersobject?명령 파라미터 (Key-Value 딕셔너리)
priorityint우선순위 (기본값: 0)
timestampstring명령 발행 시각 (ISO 8601, 기본값: 현재 시각)

응답 (200 OK - 성공):

{
"commandId": "cmd-12345",
"success": true,
"message": null,
"data": null,
"completedAt": "2026-02-17T10:45:02Z"
}

응답 (400 Bad Request - ID 불일치):

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Device ID mismatch"
}

응답 (403 Forbidden - 안전성 위반):

{
"message": "Safety violation",
"reason": "Geofence boundary exceeded: target position (100, 200, 50) is outside allowed zone"
}

응답 (404 Not Found - 장비 없음):

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404
}

CommandResult 응답 필드:

필드타입설명
commandIdstring명령 ID
successbool실행 성공 여부
messagestring?에러 메시지 (실패 시)
dataobject?반환 데이터 (선택적)
completedAtstring완료 시각 (ISO 8601, UTC)

DTO 정의

CreateDeviceRequest

public record CreateDeviceRequest(
string DeviceId,
string Name,
string? Description = null
);

DeviceCommand

public record DeviceCommand(
string CommandId,
string DeviceId,
string CommandType,
Dictionary<string, object>? Parameters = null,
int Priority = 0
)
{
public DateTimeOffset Timestamp { get; init; } = DateTimeOffset.UtcNow;
}

CommandResult

public record CommandResult(
string CommandId,
bool Success,
string? Message = null,
object? Data = null
)
{
public DateTimeOffset CompletedAt { get; init; } = DateTimeOffset.UtcNow;

public static CommandResult Succeeded(string commandId, object? data = null);
public static CommandResult Failed(string commandId, string message);
}

Device

public class Device
{
public string DeviceId { get; }
public string? TenantId { get; }
public string Name { get; }
public DeviceState CurrentState { get; }
public DateTimeOffset LastSeen { get; }
}

DeviceState (열거형)

public enum DeviceState
{
Unknown,
Provisioned,
Offline,
Online,
Idle,
Working,
Error,
Maintenance,
Decommissioned
}

에러 코드

HTTP 상태설명대응 방법
200성공-
201리소스 생성 성공Location 헤더에서 리소스 URL 확인
400잘못된 요청 (필수 필드 누락, ID 불일치)요청 본문 및 파라미터 확인
401인증 실패 (JWT 토큰 없음/만료)토큰 갱신
403권한 없음 (안전성 위반)Safety Policy 위반 사유 확인
404장비 없음장비 ID 확인
500서버 내부 오류로그 확인

사용 예제

C# (HttpClient)

using System.Net.Http.Json;
using Caffeine.Robotics.Abstractions.Models;

var client = new HttpClient
{
BaseAddress = new Uri("http://localhost:5200")
};
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);

// 전체 장비 목록 조회
var devices = await client.GetFromJsonAsync<List<Device>>("/api/v1/devices");
foreach (var device in devices)
{
Console.WriteLine($"{device.DeviceId}: {device.Name} ({device.CurrentState})");
}

// 특정 장비 조회
var device = await client.GetFromJsonAsync<Device>("/api/v1/devices/robot-arm-001");
Console.WriteLine($"Last Seen: {device?.LastSeen}");

// 신규 장비 프로비저닝
var createRequest = new CreateDeviceRequest(
DeviceId: "agv-003",
Name: "AGV #3",
Description: "Warehouse autonomous vehicle"
);
var response = await client.PostAsJsonAsync("/api/v1/devices", createRequest);
var newDevice = await response.Content.ReadFromJsonAsync<Device>();
Console.WriteLine($"Created: {newDevice?.DeviceId}");

// 명령 실행
var command = new DeviceCommand(
CommandId: "cmd-12345",
DeviceId: "robot-arm-001",
CommandType: "MoveTo",
Parameters: new Dictionary<string, object>
{
["x"] = 100,
["y"] = 200,
["z"] = 50,
["speed"] = 0.5
},
Priority: 1
);
var cmdResponse = await client.PostAsJsonAsync("/api/v1/devices/robot-arm-001/commands", command);
var result = await cmdResponse.Content.ReadFromJsonAsync<CommandResult>();
Console.WriteLine($"Command Result: {result?.Success}, Message: {result?.Message}");

curl

# 전체 장비 목록 조회
curl -H "Authorization: Bearer <token>" \
http://localhost:5200/api/v1/devices

# 특정 장비 조회
curl -H "Authorization: Bearer <token>" \
http://localhost:5200/api/v1/devices/robot-arm-001

# 신규 장비 프로비저닝
curl -X POST http://localhost:5200/api/v1/devices \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"deviceId": "agv-003",
"name": "AGV #3",
"description": "Warehouse autonomous vehicle"
}'

# 명령 실행
curl -X POST http://localhost:5200/api/v1/devices/robot-arm-001/commands \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"commandId": "cmd-12345",
"deviceId": "robot-arm-001",
"commandType": "MoveTo",
"parameters": {
"x": 100,
"y": 200,
"z": 50,
"speed": 0.5
},
"priority": 1
}'

PowerShell

$headers = @{ Authorization = "Bearer <token>" }
$baseUrl = "http://localhost:5200"

# 전체 장비 목록 조회
$devices = Invoke-RestMethod -Uri "$baseUrl/api/v1/devices" -Headers $headers
$devices | ForEach-Object { Write-Host "$($_.deviceId): $($_.name) ($($_.currentState))" }

# 특정 장비 조회
$device = Invoke-RestMethod -Uri "$baseUrl/api/v1/devices/robot-arm-001" -Headers $headers
Write-Host "Last Seen: $($device.lastSeen)"

# 신규 장비 프로비저닝
$createRequest = @{
deviceId = "agv-003"
name = "AGV #3"
description = "Warehouse autonomous vehicle"
} | ConvertTo-Json

$newDevice = Invoke-RestMethod -Uri "$baseUrl/api/v1/devices" `
-Method Post -Headers $headers -Body $createRequest -ContentType "application/json"
Write-Host "Created: $($newDevice.deviceId)"

# 명령 실행
$command = @{
commandId = "cmd-12345"
deviceId = "robot-arm-001"
commandType = "MoveTo"
parameters = @{
x = 100
y = 200
z = 50
speed = 0.5
}
priority = 1
} | ConvertTo-Json

$result = Invoke-RestMethod -Uri "$baseUrl/api/v1/devices/robot-arm-001/commands" `
-Method Post -Headers $headers -Body $command -ContentType "application/json"
Write-Host "Command Result: $($result.success), Message: $($result.message)"

Safety Policy 검증

명령 실행 시 ISafetyPolicyEngine을 통해 다음 항목이 자동으로 검증됩니다:

  • Geofence: 목표 위치가 허용된 영역 내에 있는지 확인
  • Battery Level: 배터리 잔량이 안전 기준 이상인지 확인
  • Collision: 장애물과의 충돌 위험 여부 확인
  • Emergency Stop: 비상 정지 상태가 아닌지 확인

안전성 위반 시 403 Forbidden 응답과 함께 구체적인 위반 사유가 반환됩니다.


Swagger UI

개발 환경에서 Swagger UI를 통해 API를 테스트할 수 있습니다:

http://localhost:5200/swagger

관련 문서


네임스페이스: Caffeine.Robotics.Controllers DTO 네임스페이스: Caffeine.Robotics.Abstractions.Models 어셈블리: Caffeine.Robotics.dll .NET 플랫폼: .NET 10.0