Repository navigation
MQTT_SCHEMA HUB
이 문서는 Hub 팀이 작성합니다. 비어있는 항목을 채워주세요.
- 개요
- AI_Neural_TREE 구현 명세
- Smartfactory 구현 명세
- DroneCenter 구현 명세
- HydogenCenter 구현명세
- AutonomousCenter 구현명세
- QoS / 기타 설정
- 비고
| 항목 | 내용 |
|---|---|
| 제공값 |
session_id (오케스트레이션 서버에서 발급) |
| 작성 주체 | Hub 팀 (신승훈 책임) |
| 최종 수정일 | 2026-09-29 |
AI Neural Tree는 Physical AI Diorama 시스템의 중앙 허브를 시각적으로 표현하는 장치이다.
Raspberry Pi에서 MQTT Broker에 연결하여 외부 Orchestration Server의 제어 명령을 수신하고, Arduino를 통해 AI Neural Tree 전원 및 상태 LED를 제어한다.
또한 AI Neural Tree의 시스템 상태 정보를 MQTT를 통해 외부 Orchestration Server로 주기적으로 전송한다.
External Orchestration Server
│
│ MQTT
▼
Mosquitto Broker
jscouple.site
│
▼
Raspberry Pi
ai_neural_tree_control.py
│
│ USB Serial
▼
Arduino
│
┌────┼────┐
│ │ │
▼ ▼ ▼
D6 D5 D4
Relay RED GREEN
│
▼
AI Neural Tree
| 항목 | 값 |
|---|---|
| Broker | jscouple.site |
| Port | 1883 |
| Protocol | MQTT |
| Authentication | Username / Password |
| QoS | 1 |
AI Neural Tree의 기본 Topic Prefix는 다음과 같다.
diorama/ainueraltree/
| Topic | 방향 | 설명 |
|---|---|---|
diorama/ainueraltree/led |
Orchestration → AI Neural Tree | Neural Tree 전원 제어 |
diorama/ainueraltree/status |
AI Neural Tree → Orchestration | Neural Tree 상태정보 전송 |
topic readwrite diorama/ainueraltree/#| Command | 설명 |
|---|---|
LED_ON |
AI Neural Tree 전체 전원 ON |
LED_OFF |
AI Neural Tree 전체 전원 OFF |
AI Neural Tree 전체 전원을 ON하고 상태 표시 LED를 GREEN으로 변경한다.
diorama/ainueraltree/led
{
"command": "LED_ON"
}AI Neural Tree Power → ON
D6 Relay → ON
D5 RED → OFF
D4 GREEN → ON
AI Neural Tree 전체 전원을 OFF하고 상태 표시 LED를 RED로 변경한다.
diorama/ainueraltree/led
{
"command": "LED_OFF"
}AI Neural Tree Power → OFF
D6 Relay → OFF
D5 RED → ON
D4 GREEN → OFF
| Arduino PIN | 장치 | 기능 |
|---|---|---|
D6 |
Relay | AI Neural Tree 전체 전원 |
D5 |
RED LED | 대기 / 이벤트 종료 상태 |
D4 |
GREEN LED | 이벤트 실행 상태 |
Relay 제어 기준:
HIGH = Tree Power ON
LOW = Tree Power OFF
| 상태 | Tree Power | D5 RED | D4 GREEN |
|---|---|---|---|
| 초기 / 대기 | OFF | ON | OFF |
| 이벤트 실행 | ON | OFF | ON |
| 이벤트 종료 | OFF | ON | OFF |
Raspberry Pi 및 Arduino가 시작되면 기본 상태는 다음과 같다.
Tree Power : OFF
RED : ON
GREEN : OFF
AI Neural Tree는 현재 상태를 외부 Orchestration Server로 주기적으로 전송한다.
diorama/ainueraltree/status
| 항목 | 값 |
|---|---|
| 전송 주기 | 2초 |
| QoS | 1 |
| Retain | true |
Retain=true를 사용하기 때문에 Orchestration Server가 MQTT Broker에 새롭게 연결되더라도 마지막 AI Neural Tree 상태를 확인할 수 있다.
{
"device": "AI_NEURAL_TREE",
"hub_status": "ONLINE",
"tree_power": "OFF",
"ai_status": "READY",
"connected_devices": 8,
"active_scenario": "NONE",
"current_task": "IDLE",
"processed_commands": 152,
"mqtt_messages": 1284,
"avg_response_time_ms": 82,
"cpu_percent": 34.0,
"memory_percent": 46.0,
"timestamp": "2026-10-01T18:58:31+09:00"
}| 필드 | 타입 | 설명 | 데이터 생성 방식 |
|---|---|---|---|
device |
string | 장치 식별자 | 고정 |
hub_status |
string | AI Hub 상태 | 실제 프로그램 상태 |
tree_power |
string | Neural Tree 전원 상태 | 실제 제어 상태 |
ai_status |
string | AI 처리 상태 | Simulation |
connected_devices |
integer | 연결된 디바이스 수 | Simulation |
active_scenario |
string | 현재 활성 시나리오 | Simulation |
current_task |
string | 현재 처리 Task | Simulation |
processed_commands |
integer | 처리한 명령 누적 수 | 실제 카운트 |
mqtt_messages |
integer | MQTT 메시지 누적 수 | 실제 카운트 |
avg_response_time_ms |
integer | 평균 응답시간(ms) | Simulation |
cpu_percent |
float | Raspberry Pi CPU 사용률 | 실제 측정 |
memory_percent |
float | Raspberry Pi Memory 사용률 | 실제 측정 |
timestamp |
string | 상태 생성 시간 | 실제 시간 |
| 값 | 설명 |
|---|---|
ONLINE |
AI Neural Tree Hub 정상 동작 |
OFFLINE |
AI Neural Tree Hub 연결 종료 |
| 값 | 설명 |
|---|---|
READY |
명령 대기 상태 |
PROCESSING |
시나리오 또는 Task 처리 중 |
이벤트 시작:
READY
│
▼
PROCESSING
이벤트 종료:
PROCESSING
│
▼
READY
Simulation 환경에서는 다음 시나리오 값을 사용할 수 있다.
| 값 | 설명 |
|---|---|
DRONE_DELIVERY |
드론 배송 시나리오 |
SMART_FACTORY |
스마트팩토리 시나리오 |
HYDROGEN_CHARGING |
수소 충전 시나리오 |
AUTONOMOUS_DRIVING |
자율주행 시나리오 |
NONE |
활성 시나리오 없음 |
Tree OFF 상태에서는 기본적으로 다음 값을 사용한다.
NONE
Simulation 환경에서는 다음 Task 값을 사용할 수 있다.
| 값 | 설명 |
|---|---|
ROUTE_PLANNING |
이동 경로 생성 |
DATA_ANALYSIS |
데이터 분석 |
DEVICE_CONTROL |
Physical Device 제어 |
TASK_PLANNING |
Task 계획 |
IDLE |
대기 |
Tree OFF 상태에서는 다음 값을 사용한다.
IDLE
현재 AI Neural Tree에서는 실제로 취득 가능한 데이터와 Simulation Data를 함께 사용한다.
| 데이터 | 방식 |
|---|---|
| Hub Status | 실제 |
| Tree Power | 실제 |
| CPU | 실제 |
| Memory | 실제 |
| Processed Commands | 실제 |
| MQTT Messages | 실제 |
| AI Status | Simulation |
| Connected Devices | Simulation |
| Active Scenario | Simulation |
| Current Task | Simulation |
| Average Response Time | Simulation |
mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P 'PASSWORD' \
-t "diorama/ainueraltree/led" \
-m '{"command":"LED_ON"}'동작 결과:
Tree Power → ON
RED → OFF
GREEN → ON
AI Status → PROCESSING
mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P 'PASSWORD' \
-t "diorama/ainueraltree/led" \
-m '{"command":"LED_OFF"}'동작 결과:
Tree Power → OFF
RED → ON
GREEN → OFF
AI Status → READY
AI Neural Tree에서 전송하는 STATUS만 확인:
mosquitto_sub \
-h jscouple.site \
-p 1883 \
-u oc \
-P 'PASSWORD' \
-t "diorama/ainueraltree/status" \
-vAI Neural Tree에서 사용하는 전체 MQTT Topic 확인:
mosquitto_sub \
-h jscouple.site \
-p 1883 \
-u oc \
-P 'PASSWORD' \
-t "diorama/ainueraltree/#" \
-vAI Neural Tree 제어 프로그램:
/home/zer01ne/ai_neural_tree_control.py
주요 기능:
MQTT Broker 연결
│
├── diorama/ainueraltree/led Subscribe
│
├── LED_ON / LED_OFF 명령 처리
│
├── Arduino Serial 제어
│
├── Raspberry Pi CPU / Memory 측정
│
├── Simulation Data 생성
│
└── diorama/ainueraltree/status Publish
AI Neural Tree 제어 프로그램은 Raspberry Pi 부팅 시 systemd를 통해 자동 실행한다.
ai-neural-tree.service
/etc/systemd/system/ai-neural-tree.service
[Unit]
Description=AI Neural Tree MQTT Controller
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=zer01ne
WorkingDirectory=/home/zer01ne
ExecStart=/usr/bin/python3 /home/zer01ne/ai_neural_tree_control.py
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.targetsystemd 설정 반영:
sudo systemctl daemon-reload부팅 자동 실행 등록:
sudo systemctl enable ai-neural-tree.service서비스 시작:
sudo systemctl start ai-neural-tree.service서비스 상태 확인:
sudo systemctl status ai-neural-tree.service서비스 재시작:
sudo systemctl restart ai-neural-tree.service서비스 중지:
sudo systemctl stop ai-neural-tree.service실시간 로그 확인:
journalctl -u ai-neural-tree.service -fRaspberry Pi Power ON
│
▼
systemd
│
▼
ai-neural-tree.service
│
▼
ai_neural_tree_control.py
│
├──────────────────────────────┐
│ │
▼ ▼
MQTT Subscribe STATUS 생성
│ │
▼ │
diorama/ainueraltree/led │
│ │
▼ │
LED_ON / LED_OFF │
│ │
▼ │
Arduino Serial │
│ │
▼ │
D6 Relay │
D5 RED │
D4 GREEN │
│ │
▼ ▼
AI Neural Tree diorama/ainueraltree/status
│
▼
External Orchestration Server
| 기능 | Topic | 방향 | QoS | Retain |
|---|---|---|---|---|
| Neural Tree 전원 제어 | diorama/ainueraltree/led |
Orchestration → Tree | 1 | No |
| Neural Tree 상태정보 | diorama/ainueraltree/status |
Tree → Orchestration | 1 | Yes |
AI Neural Tree는 외부 Orchestration Server로부터 MQTT 제어 명령을 수신하여 물리적인 Neural Tree 전원과 상태 LED를 제어한다.
동시에 Raspberry Pi의 실제 시스템 정보와 Simulation Data를 조합하여 AI Neural Tree의 현재 상태를 외부 Orchestration Server로 지속적으로 전송한다.
Orchestration
│
│ LED_ON / LED_OFF
▼
MQTT Broker
│
▼
AI Neural Tree
│
├── Tree Power Control
├── RED / GREEN Status
│
└── Status Data
│
▼
MQTT Broker
│
▼
Orchestration
Smart Factory 디오라마는 Physical AI Orchestration Server로부터 MQTT 명령을 수신하여 생산 이벤트를 실행한다.
Raspberry Pi가 Smart Factory의 중앙 제어 Hub 역할을 수행하며 다음 장치를 통합 제어한다.
- LED Arduino
- 대형 Conveyor Arduino + Relay
- ACEBOTT ESP32
- 소형 Conveyor
- Robot Arm
생산 이벤트가 시작되면 이벤트 표시 LED가 GREEN으로 변경되고, 대형 Conveyor와 ESP32 기반 소형 Conveyor 및 Robot Arm이 순차적으로 동작한다.
Robot Arm 동작이 완료되면 모든 물리 장치를 정지한 후 LED를 RED 상태로 복귀한다.
Physical AI Orchestration Server
│
│ MQTT
▼
Raspberry Pi
Smart Factory Controller
│
├── LED Arduino
│ ├── RED LED
│ └── GREEN LED
│
├── Large Conveyor Arduino
│ └── Relay
│ └── Large Conveyor
│
└── ACEBOTT ESP32
├── Small Conveyor
└── Robot Arm
Raspberry Pi에서 실행되는 Smart Factory 제어 프로그램:
/home/zer01ne/smartfactory_control.py
| 항목 | 값 |
|---|---|
| Broker | jscouple.site |
| Port | 1883 |
| Protocol | MQTT |
| QoS | 1 |
| Authentication | ID / Password 인증 |
| 구분 | Topic | 방향 | Retain | 설명 |
|---|---|---|---|---|
| REQUEST | diorama/smartfactory/request |
Orchestration → Smart Factory | No | 제어 명령 수신 |
| RESPONSE | diorama/smartfactory/response |
Smart Factory → Orchestration | No | 명령 처리 결과 |
| STATUS | diorama/smartfactory/status |
Smart Factory → Orchestration | Yes | 현재 시스템 상태 |
| TELEMETRY | diorama/smartfactory/telemetry |
Smart Factory → Orchestration | No | Smart Factory 운영 정보 |
Smart Factory의 공식 제어 Command는 다음과 같다.
| Command | 설명 |
|---|---|
START_SCENARIO |
생산 이벤트 시작 |
STOP_SCENARIO |
생산 이벤트 중지 |
STATUS_REQUEST |
현재 생산 및 장치 상태 요청 |
LED_ON |
Smart Factory 이벤트 LED GREEN ON |
LED_OFF |
Smart Factory 이벤트 LED GREEN OFF / RED ON |
LED_ON, LED_OFF 명령은 Robot Arm 및 Conveyor를 동작시키지 않고 LED만 독립적으로 제어한다.
diorama/smartfactory/request
{
"session_id": "SESSION-20261001-0001",
"scenario_id": "SCN-SF-001",
"command": "START_SCENARIO",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:00:00+09:00"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
session_id |
string | Y | Orchestration Server의 실행 세션 식별자 |
scenario_id |
string | Y | 실행 시나리오 식별자 |
command |
string | Y | Smart Factory 제어 명령 |
target |
string | Y | 제어 대상. SMART_FACTORY
|
payload |
object | Y | Command별 추가 전달 데이터 |
timestamp |
string | Y | 요청 생성 시각. ISO 8601 형식 |
scenario_id는 Orchestration Server에서 생성한 UUID 또는 시스템에서 정의한 고유 시나리오 ID를 사용할 수 있다.
예:
SCN-SF-001
또는:
550e8400-e29b-41d4-a716-446655440000
생산 이벤트 전체를 실행한다.
{
"session_id": "SESSION-20261001-0001",
"scenario_id": "SCN-SF-001",
"command": "START_SCENARIO",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:00:00+09:00"
}START_SCENARIO
│
▼
LED GREEN ON
│
▼
Large Conveyor ON
│
▼
ESP32 START_EVENT
│
▼
Small Conveyor 왕복 동작
│
▼
Robot Arm 1차 동작
│
▼
Robot Arm 2차 동작
│
▼
Robot Arm HOME
│
▼
ESP32 EVENT_COMPLETE
│
▼
Robot Arm 안정화 대기
│
▼
Large Conveyor OFF
│
▼
물리 장치 동작 완료
│
▼
LED GREEN OFF
LED RED ON
│
▼
STATUS COMPLETE
│
▼
RESPONSE SUCCESS
실행 중인 Smart Factory 생산 이벤트의 종료를 요청한다.
{
"session_id": "SESSION-20261001-0002",
"scenario_id": "SCN-SF-001",
"command": "STOP_SCENARIO",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:01:00+09:00"
}Large Conveyor OFF
ESP32 STOP_EVENT
LED GREEN OFF
LED RED ON
Factory State → READY
현재 Smart Factory 상태를 요청한다.
{
"session_id": "SESSION-20261001-0003",
"scenario_id": "SCN-SF-001",
"command": "STATUS_REQUEST",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:02:00+09:00"
}요청을 수신하면 현재 상태를 STATUS Topic과 RESPONSE Topic으로 전송한다.
Smart Factory의 이벤트 LED만 독립적으로 GREEN 상태로 변경한다.
Robot Arm과 Conveyor는 동작하지 않는다.
{
"session_id": "SESSION-20261001-0004",
"scenario_id": "SCN-SF-LED-001",
"command": "LED_ON",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:03:00+09:00"
}RED LED OFF
GREEN LED ON
Smart Factory 이벤트 LED를 평상시 상태로 복귀시킨다.
Robot Arm과 Conveyor에는 영향을 주지 않는다.
{
"session_id": "SESSION-20261001-0005",
"scenario_id": "SCN-SF-LED-001",
"command": "LED_OFF",
"target": "SMART_FACTORY",
"payload": {},
"timestamp": "2026-10-01T17:04:00+09:00"
}GREEN LED OFF
RED LED ON
diorama/smartfactory/response
Smart Factory는 명령 수행 결과를 RESPONSE Topic으로 전송한다.
{
"session_id": "SESSION-20261001-0001",
"scenario_id": "SCN-SF-001",
"command": "START_SCENARIO",
"target": "SMART_FACTORY",
"result": "SUCCESS",
"message": "SMART FACTORY EVENT COMPLETE",
"payload": {
"factory": "READY",
"event_running": false,
"event_step": "COMPLETE",
"event_progress": 100,
"led": "RED",
"large_conveyor": "STOPPED",
"small_conveyor": "STOPPED",
"robot_arm": "IDLE",
"robot_run_count": 2
},
"timestamp": "2026-10-01T17:05:00+09:00"
}| 필드 | 타입 | 설명 |
|---|---|---|
session_id |
string | REQUEST의 Session ID |
scenario_id |
string | REQUEST의 Scenario ID |
command |
string | 수행한 Command |
target |
string | SMART_FACTORY |
result |
string | 명령 처리 결과 SUCCESS / FAIL
|
message |
string | 명령 처리 결과 메시지 |
payload |
object | 명령 처리 후 Smart Factory 상태 |
timestamp |
string | 응답 생성 시각 |
diorama/smartfactory/status
STATUS는 Smart Factory의 현재 제어 상태와 장치 연결 상태를 전달한다.
STATUS 메시지는 Retained Message로 발행하며 기본 발행 주기는 10초이다. 주요 상태 변경 시에도 발행한다.
{
"target": "SMART_FACTORY",
"connection": "ONLINE",
"factory": "OPERATING",
"event_running": true,
"event_step": "ROBOT_ARM_RUN_1",
"event_progress": 40,
"led": {
"state": "GREEN",
"connection": "ONLINE"
},
"large_conveyor": {
"state": "RUNNING",
"connection": "ONLINE"
},
"small_conveyor": {
"state": "RUNNING"
},
"robot_arm": {
"state": "RUN_1",
"run_count": 0
},
"esp32": {
"connection": "ONLINE"
},
"production_completed": 18,
"last_error": "",
"timestamp": "2026-10-01T17:00:10+09:00"
}| 필드 | 값 예시 | 설명 |
|---|---|---|
connection |
ONLINE |
Smart Factory Hub 상태 |
factory |
READY, OPERATING, ERROR
|
공장 제어 상태 |
event_running |
true, false
|
이벤트 실행 여부 |
event_step |
READY, ROBOT_ARM_RUN_1, COMPLETE
|
현재 이벤트 단계 |
event_progress |
0~100 |
이벤트 진행률 |
led.state |
RED, GREEN
|
이벤트 LED 상태 |
large_conveyor.state |
RUNNING, STOPPED
|
대형 Conveyor 상태 |
small_conveyor.state |
RUNNING, STOPPED
|
소형 Conveyor 상태 |
robot_arm.state |
IDLE, RUN_1, RUN_2, RETURN_HOME
|
Robot Arm 상태 |
robot_arm.run_count |
0~2 |
Robot Arm 완료 횟수 |
last_error |
string | 마지막 오류 정보 |
diorama/smartfactory/telemetry
Smart Factory의 생산 및 운영 정보를 Orchestration Server로 전송한다.
기본 전송 주기는 3초이다.
{
"target": "SMART_FACTORY",
"factory": {
"status": "RUNNING"
},
"production": {
"progress_percent": 72,
"completed": 18,
"target": 25
},
"robot_arm": {
"status": "ASSEMBLING"
},
"conveyor": {
"status": "RUNNING",
"speed_percent": 65
},
"quality": {
"result": "PASS",
"defect_rate_percent": 1.2
},
"energy": {
"power_kw": 2.4
},
"environment": {
"temperature_c": 25.3
},
"devices": {
"led_arduino": "ONLINE",
"large_conveyor": "ONLINE",
"acebott_esp32": "ONLINE"
},
"event": {
"running": true,
"step": "ROBOT_ARM_RUN_1",
"progress": 40
},
"timestamp": "2026-10-01T17:00:12+09:00"
}| 구분 | 데이터 | 예시 | 설명 |
|---|---|---|---|
| 공장 | 가동 상태 | RUNNING |
Smart Factory 가동 상태 |
| 생산 | 생산 진행률 | 72 % |
생산 이벤트 진행 정보 |
| 생산 | 생산 수량 | 18 / 25 |
완료 수량 / 목표 수량 |
| Robot Arm | 상태 | ASSEMBLING |
Robot Arm 작업 상태 |
| Conveyor | 상태 | RUNNING |
Conveyor 동작 상태 |
| Conveyor | 속도 | 65 % |
Conveyor 운영 속도 |
| 품질 | 검사 결과 | PASS |
품질검사 결과 |
| 품질 | 불량률 | 1.2 % |
생산 품질 운영 정보 |
| 에너지 | 전력 사용량 | 2.4 kW |
공장 전력 사용 정보 |
| 환경 | 공장 온도 | 25.3 °C |
공장 환경 온도 |
| 장치 | LED Arduino | ONLINE |
LED Controller 연결 상태 |
| 장치 | Large Conveyor | ONLINE |
대형 Conveyor Controller 연결 상태 |
| 장치 | ACEBOTT ESP32 | ONLINE |
Robot Arm Controller 연결 상태 |
| 이벤트 | 실행 상태 | true |
현재 이벤트 실행 여부 |
| 이벤트 | 이벤트 단계 | ROBOT_ARM_RUN_1 |
현재 시나리오 실행 단계 |
| 이벤트 | 진행률 | 40 |
현재 시나리오 진행률 |
| Event Step | Progress | 설명 |
|---|---|---|
READY |
0 | 이벤트 대기 |
EVENT_START |
5 | 이벤트 시작 |
LED_GREEN |
10 | GREEN LED 활성화 |
LARGE_CONVEYOR_RUNNING |
15 | 대형 Conveyor 동작 |
ESP32_COMMAND_RECEIVED |
22 | ESP32 이벤트 명령 수신 |
ESP32_EVENT_RUNNING |
25 | ESP32 이벤트 시작 |
SMALL_CONVEYOR_RUNNING |
30 | 소형 Conveyor 동작 |
ROBOT_ARM_RUN_1 |
40 | Robot Arm 1차 작업 |
ROBOT_RUN_1_COMPLETE |
55 | Robot Arm 1차 작업 완료 |
ROBOT_ARM_RUN_2 |
65 | Robot Arm 2차 작업 |
ROBOT_RUN_2_COMPLETE |
85 | Robot Arm 2차 작업 완료 |
FINAL_HOME |
90 | Robot Arm 원위치 복귀 |
ESP32_COMPLETE |
95 | ESP32 이벤트 완료 |
ROBOT_COMPLETE_WAIT |
96 | Robot Arm 안정화 |
LARGE_CONVEYOR_STOPPED |
98 | 대형 Conveyor 종료 |
COMPLETE |
100 | 전체 생산 이벤트 완료 |
ERROR |
- | 이벤트 오류 |
Smart Factory는 USB Serial 연결을 사용한다.
장치 번호가 재부팅 시 변경되는 문제를 방지하기 위해 /dev/ttyUSB0 방식 대신 /dev/serial/by-path/ 경로를 사용한다.
| 장치 | 물리 USB | Serial 설정 |
|---|---|---|
| ACEBOTT ESP32 | USB 1.1 | 115200 bps |
| LED Arduino | USB 1.2 | 9600 bps |
| Large Conveyor Arduino | USB 1.3 | 9600 bps |
/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.1:1.0-port0
/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.2:1.0
/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3:1.0-port0
| 상태 | RED | GREEN |
|---|---|---|
| 평상시 | ON | OFF |
| 이벤트 실행 | OFF | ON |
| 이벤트 완료 | ON | OFF |
Arduino Pin:
D6 = RED
D7 = GREEN
Raspberry Pi와 ACEBOTT ESP32 사이에서는 USB Serial Command를 사용한다.
| Command | 설명 |
|---|---|
START_EVENT |
Smart Factory Robot/Conveyor 이벤트 시작 |
STOP_EVENT |
이벤트 종료 요청 |
STATUS |
ESP32 상태 요청 |
PING |
ESP32 통신 확인 |
ESP32는 전체 생산 동작 완료 후 다음 메시지를 Raspberry Pi로 전송한다.
EVENT_COMPLETE
Raspberry Pi는 EVENT_COMPLETE를 수신한 후 Robot Arm의 최종 동작 안정화 시간을 확보하고 대형 Conveyor와 LED를 순차적으로 종료한다.
Smart Factory Controller는 Raspberry Pi 부팅 시 systemd를 통해 자동 실행한다.
Service:
smartfactory.service
실행 프로그램:
/home/zer01ne/smartfactory_control.py
상태 확인:
systemctl status smartfactory.service실시간 로그:
journalctl -u smartfactory.service -f재시작:
sudo systemctl restart smartfactory.servicemosquitto_sub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/#' \
-q 1 \
-vmosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/request' \
-q 1 \
-m '{"session_id":"TEST-001","scenario_id":"SCN-SF-001","command":"START_SCENARIO","target":"SMART_FACTORY","payload":{}}'mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/request' \
-q 1 \
-m '{"session_id":"TEST-002","scenario_id":"SCN-SF-001","command":"STOP_SCENARIO","target":"SMART_FACTORY","payload":{}}'mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/request' \
-q 1 \
-m '{"session_id":"TEST-003","scenario_id":"SCN-SF-001","command":"STATUS_REQUEST","target":"SMART_FACTORY","payload":{}}'mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/request' \
-q 1 \
-m '{"session_id":"TEST-004","scenario_id":"SCN-SF-LED","command":"LED_ON","target":"SMART_FACTORY","payload":{}}'mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/smartfactory/request' \
-q 1 \
-m '{"session_id":"TEST-005","scenario_id":"SCN-SF-LED","command":"LED_OFF","target":"SMART_FACTORY","payload":{}}'START_SCENARIO
STOP_SCENARIO
STATUS_REQUEST
LED_ON
LED_OFF
diorama/smartfactory/request
diorama/smartfactory/response
diorama/smartfactory/status
diorama/smartfactory/telemetry
Physical AI Orchestration
│
│ REQUEST
▼
diorama/smartfactory/request
│
▼
┌───────────────────────────────┐
│ SMART FACTORY HUB │
│ Raspberry Pi │
│ │
│ START_SCENARIO │
│ STOP_SCENARIO │
│ STATUS_REQUEST │
│ LED_ON │
│ LED_OFF │
└───────────────┬───────────────┘
│
┌───────┼────────┐
│ │ │
▼ ▼ ▼
LED Large ESP32
Arduino Conveyor │
├── Small Conveyor
└── Robot Arm
│
▼
RESPONSE / STATUS
TELEMETRY
Smart Factory는 Orchestration Server의 MQTT 명령을 기준으로 Raspberry Pi가 LED Arduino, Large Conveyor Arduino 및 ACEBOTT ESP32를 통합 제어한다.
생산 이벤트의 실행 결과는 RESPONSE, 현재 시스템 상태는 STATUS, 생산 및 운영 정보는 TELEMETRY Topic을 통해 Orchestration Server로 전달한다.
Drone Station은 Physical AI Diorama의 드론 배송 영역을 담당한다.
Raspberry Pi를 중심으로 CoDrone Mini 1대와 Arduino UNO를 연동하며, MQTT를 통해 Orchestration Server와 양방향으로 통신한다.
Orchestration Server
│
│ MQTT REQUEST
▼
Raspberry Pi
│
├── CoDrone Mini
│
└── Arduino UNO
├── D6 RED LED
└── D7 GREEN LED
│
│ MQTT STATUS / RESPONSE
▼
Orchestration Server
| 구성요소 | 역할 |
|---|---|
| Raspberry Pi | Drone Station 메인 제어 |
| CoDrone Mini | 실제 드론 비행 |
| Arduino UNO | EVENT LED 제어 |
| 3.5" LCD | Drone Station GUI |
| MQTT Broker | Orchestration Server 연동 |
GUI 해상도:
480 × 320
Drone Control Python 파일:
/home/zer01ne/drone_control.py
Host : jscouple.site
Port : 1883
Username : oc
Password : 1234
Python MQTT Library:
paho-mqtt
Drone Station Prefix:
diorama/dronestation/
| 구분 | Topic | 방향 |
|---|---|---|
| REQUEST | diorama/dronestation/request |
Orchestration → Drone Station |
| RESPONSE | diorama/dronestation/response |
Drone Station → Orchestration |
| STATUS | diorama/dronestation/status |
Drone Station → Orchestration |
diorama/dronestation/request
Orchestration Server에서 Drone Station EVENT 실행 명령을 전달한다.
{
"session_id": "SESSION-20261001-0001",
"scenario_id": "SCN-DRONE-001",
"command": "START_SCENARIO",
"target": "DRONE",
"payload": {
"from": "P1",
"to": "P2",
"delivery_type": "MEDICINE"
},
"timestamp": "2026-10-01T19:46:00+09:00"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
session_id |
string | Y | Orchestration Session ID |
scenario_id |
string | Y | Scenario 식별 ID |
command |
string | Y | 실행 명령 |
target |
string | Y | 제어 대상 |
payload |
object | Y | EVENT 실행 데이터 |
timestamp |
string | Y | 요청 생성 시간 |
| 필드 | 타입 | 설명 |
|---|---|---|
from |
string | 출발 위치 |
to |
string | 도착 위치 |
delivery_type |
string | 배송 종류 |
배송 종류:
MEDICINE
GROCERY
기본 이동 구간:
P1 → P2
| Command | 설명 |
|---|---|
START_SCENARIO |
Drone 배송 EVENT 실행 |
Target:
DRONE
START_SCENARIO를 수신하면 다음 순서로 EVENT를 실행한다.
START_SCENARIO
│
▼
REQUEST 검증
│
▼
RESPONSE = ACCEPTED
│
▼
Station = OPERATING
Progress = 10%
│
▼
Arduino EVENT_ON
│
├── D6 RED OFF
└── D7 GREEN ON
│
▼
CoDrone TAKE OFF
│
▼
저고도 보정
│
▼
HOVER 2 SEC
│
├── Drone = FLYING
└── Progress = 65%
│
▼
LANDING
│
└── Progress = 90%
│
▼
LAND
│
▼
Arduino EVENT_OFF
│
├── D6 RED ON
└── D7 GREEN OFF
│
▼
EVENT COMPLETE
│
├── Station = READY
├── Drone = DOCKED
├── Progress = 100%
└── Complete = TRUE
│
▼
RESPONSE = COMPLETE
| 상태 | 설명 |
|---|---|
READY |
EVENT 대기 |
TAKEOFF |
드론 이륙 |
HOVER |
Hover 수행 |
LANDING |
착륙 진행 |
COMPLETE |
EVENT 완료 |
| 상태 | 설명 |
|---|---|
READY |
EVENT 대기 |
OPERATING |
EVENT 실행 중 |
상태 변화:
EVENT 대기
READY
↓
EVENT 실행
OPERATING
↓
EVENT 완료
READY
현재 Drone Station은 실제 CoDrone Mini 1대를 사용한다.
따라서 Drone 1, Drone 2로 구분하지 않고 drone 하나만 사용한다.
| 상태 | 설명 |
|---|---|
OFFLINE |
Drone 연결 안 됨 |
DOCKED |
Drone 연결 및 대기 |
FLYING |
Drone 비행 중 |
diorama/dronestation/status
전송 주기:
2 SEC
STATUS는 MQTT Retained Message로 전송한다.
{
"device": "DRONESTATION",
"timestamp": "2026-10-01T19:46:00+09:00",
"station": {
"status": "OPERATING"
},
"drone": {
"status": "FLYING",
"battery_percent": 81,
"altitude_m": 0.23,
"speed_mps": 0.08
},
"delivery": {
"type": "MEDICINE",
"progress_percent": 65,
"from": "P1",
"to": "P2",
"complete": false
}
}| 필드 | 타입 | 설명 |
|---|---|---|
device |
string | Device 구분 |
timestamp |
string | 데이터 생성 시간 |
station |
object | Drone Station 상태 |
drone |
object | Drone 상태 |
delivery |
object | 배송 EVENT 상태 |
| 필드 | 타입 | 값 |
|---|---|---|
status |
string | READY / OPERATING |
| 필드 | 타입 | 설명 |
|---|---|---|
status |
string | OFFLINE / DOCKED / FLYING |
battery_percent |
number | 배터리 잔량 |
altitude_m |
number | 현재 고도 |
speed_mps |
number | 현재 속도 |
| 필드 | 타입 | 설명 |
|---|---|---|
type |
string | MEDICINE / GROCERY |
progress_percent |
integer | 배송 진행률 |
from |
string | 출발 위치 |
to |
string | 도착 위치 |
complete |
boolean | 배송 완료 여부 |
| 표시 항목 | MQTT 필드 | 값 |
|---|---|---|
| 스테이션 상태 | station.status |
READY / OPERATING |
| Drone 상태 | drone.status |
OFFLINE / DOCKED / FLYING |
| 배송 종류 | delivery.type |
MEDICINE / GROCERY |
| 배송 진행률 | delivery.progress_percent |
0 ~ 100% |
| 배터리 | drone.battery_percent |
% |
| 고도 | drone.altitude_m |
m |
| 속도 | drone.speed_mps |
m/s |
| 현재 위치/구간 |
delivery.from → delivery.to
|
P1 → P2 |
| 배송 완료 여부 | delivery.complete |
TRUE / FALSE |
| EVENT 상태 | 진행률 |
|---|---|
| READY | 0% |
| START | 10% |
| HOVER | 65% |
| LANDING | 90% |
| COMPLETE | 100% |
완료 상태:
{
"progress_percent": 100,
"complete": true
}다음 정보는 실제 프로그램 및 장치의 상태를 기준으로 한다.
Station 상태
Drone 연결 상태
Drone 비행 상태
EVENT 상태
Arduino LED 제어 상태
MQTT 연결 상태
현재 CoDrone에서 직접 취득하지 않는 다음 값은 전시 및 통합 테스트용으로 동적으로 생성한다.
Battery
Altitude
Speed
EVENT 대기 상태:
Altitude = 0.0 m
Speed = 0.0 m/s
비행 중에는 EVENT 상태에 맞춰 테스트 데이터가 변경된다.
Arduino UNO PIN 구성:
| PIN | LED | 역할 |
|---|---|---|
| D6 | RED | READY |
| D7 | GREEN | EVENT |
정상 대기:
D6 RED ON
D7 GREEN OFF
EVENT 실행:
D6 RED OFF
D7 GREEN ON
EVENT 완료:
D6 RED ON
D7 GREEN OFF
READY
결과:
RED ON
GREEN OFF
EVENT_ON
결과:
RED OFF
GREEN ON
EVENT_OFF
결과:
RED ON
GREEN OFF
Serial 통신 속도:
115200
Arduino UNO 자동 검색 기준:
VID:PID = 2341:0043
diorama/dronestation/response
REQUEST 처리 결과와 EVENT 결과를 Orchestration Server로 전달한다.
{
"device": "DRONESTATION",
"session_id": "SESSION-20261001-0001",
"scenario_id": "SCN-DRONE-001",
"result": "ACCEPTED",
"event_state": "READY",
"message": "START_SCENARIO accepted",
"timestamp": "2026-10-01T19:46:00+09:00"
}| Result | 설명 |
|---|---|
ACCEPTED |
EVENT 실행 요청 정상 접수 |
BUSY |
기존 EVENT 실행 중 |
REJECTED |
명령 또는 실행 조건 오류 |
ERROR |
REQUEST 처리 오류 |
STARTED |
EVENT 시작 |
COMPLETE |
EVENT 완료 |
터미널에서 Drone EVENT 실행:
mosquitto_pub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/dronestation/request' \
-m '{"session_id":"SESSION-TEST-001","scenario_id":"SCN-DRONE-001","command":"START_SCENARIO","target":"DRONE","payload":{"from":"P1","to":"P2","delivery_type":"MEDICINE"},"timestamp":"2026-10-01T19:46:00+09:00"}'mosquitto_sub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/dronestation/status' \
-vmosquitto_sub \
-h jscouple.site \
-p 1883 \
-u oc \
-P '1234' \
-t 'diorama/dronestation/response' \
-v소스 위치:
/home/zer01ne/drone_control.py
일반 실행:
python3 /home/zer01ne/drone_control.pySSH에서 Raspberry Pi LCD로 실행:
DISPLAY=:0 python3 /home/zer01ne/drone_control.pyDrone Station은 Raspberry Pi 부팅 시 drone_control.py가 자동 실행되도록 systemd Service를 사용한다.
Service 이름:
drone-control.service
Service 파일:
/etc/systemd/system/drone-control.service
sudo nano /etc/systemd/system/drone-control.service다음 내용을 입력한다.
[Unit]
Description=Physical AI Drone Station Control
After=graphical.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=zer01ne
WorkingDirectory=/home/zer01ne
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/zer01ne/.Xauthority
Environment=PYTHONUNBUFFERED=1
ExecStartPre=/bin/sleep 10
ExecStart=/usr/bin/python3 /home/zer01ne/drone_control.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=graphical.targetsystemd 설정 다시 읽기:
sudo systemctl daemon-reload부팅 자동 실행 활성화:
sudo systemctl enable drone-control.serviceService 시작:
sudo systemctl start drone-control.servicesudo systemctl status drone-control.service정상 실행 상태:
Active: active (running)
최근 로그:
journalctl -u drone-control.service -n 50실시간 로그:
journalctl -u drone-control.service -f정상 MQTT 연결 시:
[MQTT] CONNECTED
[MQTT] SUBSCRIBE: diorama/dronestation/request
Python 소스를 수정한 후:
sudo systemctl restart drone-control.servicesudo systemctl stop drone-control.servicesudo systemctl disable drone-control.serviceRaspberry Pi POWER ON
│
▼
Linux Boot
│
▼
Graphical Desktop
│
▼
drone-control.service
│
▼
10 SEC WAIT
│
▼
drone_control.py
│
├── 480×320 GUI
├── Arduino Serial
├── CoDrone Mini
└── MQTT
│
▼
MQTT Broker 연결
│
▼
diorama/dronestation/request
│
▼
START_SCENARIO 대기
Orchestration Server
│
│ REQUEST
▼
diorama/dronestation/request
│
▼
Raspberry Pi
│
┌──────────┴──────────┐
│ │
Arduino UNO CoDrone Mini
│ │
┌─────┴─────┐ │
│ │ │
D6 RED D7 GREEN Flight
READY EVENT
│ │
└──────────┬──────────┘
│
▼
Drone Station
│
┌─────────┴─────────┐
│ │
▼ ▼
STATUS RESPONSE
│ │
▼ ▼
diorama/dronestation/status
diorama/dronestation/response
│ │
└─────────┬─────────┘
▼
Orchestration Server
Hydrogen / Battery Diorama는 오케스트레이션 서버로부터 MQTT 명령을 수신하여 Raspberry Pi와 Arduino를 통해 수소/배터리 충전 시나리오를 실행한다.
전체 제어 구조는 다음과 같다.
Orchestration Server
|
| MQTT
v
Raspberry Pi
hydrogen_control.py
|
| USB Serial
v
Arduino
|
+-- D6 RED LED
+-- D7 GREEN LED
|
+-- D5 BLUE LED
+-- D4 BLUE LED
+-- D3 BLUE LED
+-- D2 BLUE LED
이벤트 실행 중에는 GREEN LED가 켜지고 BLUE LED가 순차적으로 점등되어 충전 상태를 표현한다.
기본 Topic Prefix:
diorama/hydrogen
| 구분 | Topic | 설명 |
|---|---|---|
| REQUEST | diorama/hydrogen/request |
오케스트레이션 → Hydrogen |
| RESPONSE | diorama/hydrogen/response |
Hydrogen → 오케스트레이션 |
| STATUS | diorama/hydrogen/status |
Hydrogen 상태 정보 송신 |
| Command | 설명 |
|---|---|
START_SCENARIO |
수소/배터리 충전 시나리오 시작 |
STOP_SCENARIO |
충전 시나리오 종료 |
GET_STATUS |
현재 Hydrogen/Battery 상태 요청 |
PING |
통신 상태 확인 |
diorama/hydrogen/request
{
"session_id": "SESSION-TEST-001",
"scenario_id": "SCN-HYDROGEN-001",
"command": "START_SCENARIO",
"target": "HYDROGEN",
"payload": {
"vehicle": "CAR1"
},
"timestamp": "2026-10-01T19:30:00+09:00"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
session_id |
string | Y | 오케스트레이션 세션 ID |
scenario_id |
string | Y | 시나리오 식별 ID |
command |
string | Y | 실행 명령 |
target |
string | Y | 대상 디오라마 |
payload |
object | Y | 명령에 필요한 상세 데이터 |
timestamp |
string | N | 요청 생성 시간 |
| 필드 | 타입 | 설명 |
|---|---|---|
vehicle |
string | 충전 대상 차량 (CAR1 등) |
{
"session_id": "SESSION-TEST-001",
"scenario_id": "SCN-HYDROGEN-001",
"command": "STOP_SCENARIO",
"target": "HYDROGEN",
"payload": {},
"timestamp": "2026-10-01T19:35:00+09:00"
}시나리오가 종료되면 충전 동작 및 BLUE LED 애니메이션이 중지된다.
diorama/hydrogen/response
{
"device": "HYDROGEN_BATTERY",
"command": "START_SCENARIO",
"result": "ACCEPTED",
"session_id": "SESSION-TEST-001",
"scenario_id": "SCN-HYDROGEN-001",
"timestamp": "2026-10-01T19:30:00+09:00"
}{
"device": "HYDROGEN_BATTERY",
"command": "STOP_SCENARIO",
"result": "COMPLETED",
"session_id": "SESSION-TEST-001",
"scenario_id": "SCN-HYDROGEN-001",
"timestamp": "2026-10-01T19:35:00+09:00"
}| 필드 | 타입 | 설명 |
|---|---|---|
device |
string | 디바이스 식별자 |
command |
string | 처리한 Command |
result |
string | 명령 처리 결과 |
session_id |
string | 세션 ID |
scenario_id |
string | 시나리오 ID |
timestamp |
string | 응답 생성 시간 |
| 값 | 설명 |
|---|---|
ACCEPTED |
시나리오 시작 명령 정상 처리 |
COMPLETED |
시나리오 종료 명령 정상 처리 |
OK |
일반 명령 정상 처리 |
ARDUINO_ERROR |
Arduino 통신 오류 |
UNKNOWN_COMMAND |
정의되지 않은 Command |
diorama/hydrogen/status
Hydrogen/Battery Controller는 현재 상태 및 충전 데이터를 오케스트레이션 서버로 주기적으로 송신한다.
기본 송신 주기는 약 1초이다.
{
"device": "HYDROGEN_BATTERY",
"station_status": "BUSY",
"charging_status": "CHARGING",
"target_vehicle": "CAR1",
"charging_progress": 64.2,
"vehicle_soc": {
"start": 42.0,
"current": 65.1,
"target": 78.0
},
"hydrogen_level": 70.1,
"supply_pressure_bar": 701.3,
"instant_power_kw": 6.2,
"cumulative_supply_kg": 2.37,
"led": {
"D6_RED": false,
"D7_GREEN": true
},
"session_id": "SESSION-TEST-001",
"scenario_id": "SCN-HYDROGEN-001",
"timestamp": "2026-10-01T19:30:00+09:00"
}| 화면 표시 항목 | MQTT 필드 | 타입 | 단위 | 예제 |
|---|---|---|---|---|
| 충전소 상태 | station_status |
string | - | BUSY |
| 충전 상태 | charging_status |
string | - | CHARGING |
| 대상 차량 | target_vehicle |
string | - | CAR1 |
| 충전 진행률 | charging_progress |
number | % | 64.2 |
| 차량 초기 SOC | vehicle_soc.start |
number | % | 42.0 |
| 차량 현재 SOC | vehicle_soc.current |
number | % | 65.1 |
| 차량 목표 SOC | vehicle_soc.target |
number | % | 78.0 |
| 수소 잔량 | hydrogen_level |
number | % | 70.1 |
| 공급 압력 | supply_pressure_bar |
number | bar | 701.3 |
| 순간 전력 | instant_power_kw |
number | kW | 6.2 |
| 누적 공급량 | cumulative_supply_kg |
number | kg | 2.37 |
station_status는 현재 충전소의 사용 가능 상태를 나타낸다.
| 값 | 설명 |
|---|---|
AVAILABLE |
충전 가능 |
BUSY |
충전 시나리오 실행 중 |
OFFLINE |
Hydrogen Controller 종료 또는 연결 해제 |
시나리오 시작:
AVAILABLE
|
START_SCENARIO
|
v
BUSY
시나리오 종료:
BUSY
|
STOP_SCENARIO
|
v
AVAILABLE
charging_status는 차량의 현재 충전 상태를 나타낸다.
| 값 | 설명 |
|---|---|
CHARGING |
충전 진행 중 |
COMPLETE |
충전 완료 또는 충전 대기 상태 |
시나리오 실행 중:
station_status = BUSY
charging_status = CHARGING
시나리오 종료 또는 충전 완료:
station_status = AVAILABLE
charging_status = COMPLETE
차량 SOC는 다음 세 가지 값으로 관리한다.
{
"vehicle_soc": {
"start": 42.0,
"current": 65.1,
"target": 78.0
}
}| 필드 | 설명 |
|---|---|
start |
충전 시작 시 SOC |
current |
현재 SOC |
target |
목표 SOC |
충전 시뮬레이션:
42%
|
v
50%
|
v
60%
|
v
70%
|
v
78%
| Arduino Pin | LED | 역할 |
|---|---|---|
| D2 | BLUE | 충전 진행 4단계 |
| D3 | BLUE | 충전 진행 3단계 |
| D4 | BLUE | 충전 진행 2단계 |
| D5 | BLUE | 충전 진행 1단계 |
| D6 | RED | IDLE / STOP |
| D7 | GREEN | RUNNING / START |
시나리오가 실행되지 않는 경우:
D2 BLUE OFF
D3 BLUE OFF
D4 BLUE OFF
D5 BLUE OFF
D6 RED ON
D7 GREEN OFF
START_SCENARIO 수신 시:
D6 RED OFF
D7 GREEN ON
BLUE LED는 충전 상태를 표현하기 위해 순차적으로 누적 점등된다.
D5
|
v
D5 + D4
|
v
D5 + D4 + D3
|
v
D5 + D4 + D3 + D2
표현되는 충전 단계:
D5 25%
D5 + D4 50%
D5 + D4 + D3 75%
D5 + D4 + D3 + D2 100%
100% 표시 후 BLUE LED를 모두 끄고 RUNNING 상태에서는 다시 반복한다.
STOP_SCENARIO를 수신하면 BLUE LED 애니메이션을 즉시 중지한다.
D2 BLUE OFF
D3 BLUE OFF
D4 BLUE OFF
D5 BLUE OFF
D6 RED ON
D7 GREEN OFF
Serial Baudrate:
115200
| Command | 설명 |
|---|---|
START |
충전 이벤트 시작 |
STOP |
충전 이벤트 종료 |
STATUS |
Arduino 상태 요청 |
PING |
Serial 통신 확인 |
| Message | 설명 |
|---|---|
READY:HYDROGEN_CONTROLLER |
Arduino 준비 완료 |
RX:START |
START 명령 수신 |
ACK:START |
START 처리 완료 |
STATUS:RUNNING |
이벤트 실행 중 |
RX:STOP |
STOP 명령 수신 |
ACK:STOP |
STOP 처리 완료 |
STATUS:IDLE |
이벤트 대기 상태 |
PONG |
PING 응답 |
CHARGING:25 |
BLUE LED 25% 단계 |
CHARGING:50 |
BLUE LED 50% 단계 |
CHARGING:75 |
BLUE LED 75% 단계 |
CHARGING:100 |
BLUE LED 100% 단계 |
Orchestration Server
|
| START_SCENARIO
v
MQTT Broker
|
v
diorama/hydrogen/request
|
v
Raspberry Pi
hydrogen_control.py
|
| Serial START
v
Arduino
|
+----------------------+
| |
v v
D7 GREEN ON BLUE Charging LED
|
v
D5
|
v
D5 + D4
|
v
D5 + D4 + D3
|
v
D5 + D4 + D3 + D2
Raspberry Pi
|
| MQTT STATUS
v
diorama/hydrogen/status
|
v
Orchestration Server
mosquitto_sub -h jscouple.site -p 1883 -u oc -P 1234 \
-t "diorama/hydrogen/#" -vmosquitto_pub -h jscouple.site -p 1883 -u oc -P 1234 \
-t "diorama/hydrogen/request" \
-m '{"session_id":"SESSION-TEST-001","scenario_id":"SCN-HYDROGEN-001","command":"START_SCENARIO","target":"HYDROGEN","payload":{"vehicle":"CAR1"}}'정상 동작:
RED OFF
GREEN ON
BLUE LED
D5 -> D5+D4 -> D5+D4+D3 -> D5+D4+D3+D2
station_status = BUSY
charging_status = CHARGING
mosquitto_pub -h jscouple.site -p 1883 -u oc -P 1234 \
-t "diorama/hydrogen/request" \
-m '{"session_id":"SESSION-TEST-001","scenario_id":"SCN-HYDROGEN-001","command":"STOP_SCENARIO","target":"HYDROGEN","payload":{}}'정상 동작:
BLUE OFF
GREEN OFF
RED ON
station_status = AVAILABLE
charging_status = COMPLETE
Python Controller:
/home/zer01ne/hydrogen_control.py
실행:
python3 /home/zer01ne/hydrogen_control.py서비스 파일:
/etc/systemd/system/hydrogen.service
서비스 설정:
[Unit]
Description=Hydrogen Battery Diorama MQTT Controller
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=zer01ne
WorkingDirectory=/home/zer01ne
ExecStart=/usr/bin/python3 /home/zer01ne/hydrogen_control.py
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target서비스 등록:
sudo systemctl daemon-reload
sudo systemctl enable hydrogen.service
sudo systemctl start hydrogen.service서비스 재시작:
sudo systemctl restart hydrogen.service서비스 상태 확인:
sudo systemctl status hydrogen.service자동 실행 확인:
systemctl is-enabled hydrogen.service정상:
enabled
실행 상태 확인:
systemctl is-active hydrogen.service정상:
active
실시간 로그:
journalctl -u hydrogen.service -f Orchestration Server
|
| MQTT
v
MQTT Broker
|
v
Raspberry Pi Controller
hydrogen_control.py
|
| USB Serial
v
Arduino
|
+-----------+-----------+
| |
v v
Event Status LED Charging LED
D6 / D7 D5/D4/D3/D2
|
v
Hydrogen / Battery
Diorama
Hydrogen / Battery Diorama는 오케스트레이션 서버의 MQTT 명령을 기반으로 충전 이벤트를 실행하고, 충전소 상태, 충전 상태, 대상 차량, 충전 진행률, 차량 SOC, 수소 잔량, 공급 압력, 순간 전력 및 누적 공급량을 MQTT STATUS Topic을 통해 오케스트레이션 서버로 전달한다.
Autonomous Center는 Physical AI 기반 자율주행 차량의 이동 및 도로 상황을 표현한다.
총 4대의 자율주행 차량을 각각 독립적인 MQTT Topic으로 관리한다.
CAR1
CAR2
CAR3
CAR4
| Command | 설명 |
|---|---|
START_SCENARIO |
자율주행 시나리오 시작 |
STOP_SCENARIO |
자율주행 시나리오 종료 |
MOVE |
차량 이동 |
STOP |
차량 정지 |
LED_ON |
차량 LED 켜기 — 실제 command 값은 car1_led_on (아래 2.1) |
LED_OFF |
차량 LED 끄기 — 실제 command 값은 car1_led_off (아래 2.1) |
STATUS_REQUEST |
차량 상태 요청 |
차량 LED 제어. 장치로 보내는 command 값은 차 번호와 무관하게 4대 모두 고정이다 —
CAR2~CAR4 에도 car1_led_on / car1_led_off 를 보낸다. 어느 차인지는 토픽으로 구분한다.
| 오케스트레이션 명령 | 실제 command 값 (CAR1~CAR4 공통) |
|---|---|
LED_ON |
car1_led_on |
LED_OFF |
car1_led_off |
오케스트레이션 서버(자동화·백오피스)에서는 LED_ON / LED_OFF 로 고르고, 서버가 발행할 때 위 값으로 바꿔 보낸다
(internal/mqttx/hub_catalog.go 의 HubCommand.Wire). payload 는 쓰지 않는다 ({}).
diorama/autonomouscar/car3/request
{
"session_id": "SESSION-20260929-0005",
"scenario_id": "SCN-AUTO-LED-001",
"command": "car1_led_on",
"target": "CAR3",
"payload": {},
"timestamp": "2026-10-09T17:00:00+09:00"
}응답은 다른 명령과 같이 diorama/autonomouscar/{car_id}/response 로 온다고 본다. 서버는 응답의 command 가
car1_led_on 이든 LED_ON 이든 (session_id, scenario_id) 로 요청을 찾는다. 응답이 없으면 큐 타임아웃(30초)으로 끝난다.
각 차량은 다음 Topic 구조를 사용한다.
diorama/autonomouscar/{car_id}/request
diorama/autonomouscar/{car_id}/response
diorama/autonomouscar/{car_id}/status
diorama/autonomouscar/car1/request
diorama/autonomouscar/car1/response
diorama/autonomouscar/car1/status
diorama/autonomouscar/car2/request
diorama/autonomouscar/car2/response
diorama/autonomouscar/car2/status
diorama/autonomouscar/car3/request
diorama/autonomouscar/car3/response
diorama/autonomouscar/car3/status
diorama/autonomouscar/car4/request
diorama/autonomouscar/car4/response
diorama/autonomouscar/car4/status
diorama/autonomouscar/car1/request
{
"session_id": "SESSION-20260929-0005",
"scenario_id": "SCN-AUTO-001",
"command": "START_SCENARIO",
"target": "CAR1",
"payload": {
"from": "STATION_A",
"to": "HYDROGEN_CENTER"
},
"timestamp": "2026-09-29T08:40:00+09:00"
}| 필드 | 타입 | 필수 | 설명 | 예시 |
|---|---|---|---|---|
session_id |
string | Y | Orchestration 실행 세션 ID | SESSION-20260929-0005 |
scenario_id |
string | Y | 자율주행 시나리오 ID | SCN-AUTO-001 |
command |
string | Y | 차량 제어 명령 | START_SCENARIO |
target |
string | Y | 제어 대상 차량 | CAR1 |
payload |
object | Y | 주행 관련 Parameter (LED_ON/LED_OFF 는 {}) |
{...} |
timestamp |
string | Y | 명령 생성 시간 | 2026-09-29T08:40:00+09:00 |
| 값 | 설명 |
|---|---|
CAR1 |
자율주행 차량 1 |
CAR2 |
자율주행 차량 2 |
CAR3 |
자율주행 차량 3 |
CAR4 |
자율주행 차량 4 |
| 필드 | 타입 | 필수 | 설명 | 예시 |
|---|---|---|---|---|
from |
string | Y | 차량 출발 위치 | STATION_A |
to |
string | Y | 차량 목적지 | HYDROGEN_CENTER |
diorama/autonomouscar/car1/response
{
"session_id": "SESSION-20260929-0005",
"scenario_id": "SCN-AUTO-001",
"command": "START_SCENARIO",
"target": "CAR1",
"result": "SUCCESS",
"message": "Autonomous driving scenario completed",
"payload": {
"destination_reached": true,
"final_position": "HYDROGEN_CENTER"
},
"timestamp": "2026-09-29T08:40:20+09:00"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
session_id |
string | Y | REQUEST와 동일한 Session ID |
scenario_id |
string | Y | REQUEST와 동일한 Scenario ID |
command |
string | Y | 처리한 Command |
target |
string | Y | 명령을 수행한 차량 ID |
result |
string | Y | 명령 처리 결과 |
message |
string | Y | 처리 결과 설명 |
payload |
object | N | 주행 처리 결과 |
timestamp |
string | Y | RESPONSE 생성 시간 |
| 필드 | 타입 | 설명 |
|---|---|---|
destination_reached |
boolean | 목적지 도착 여부 |
final_position |
string | 이벤트 종료 시 차량 위치 |
| Result | 설명 |
|---|---|
SUCCESS |
주행 이벤트 정상 완료 |
FAILED |
주행 이벤트 실패 |
BUSY |
차량이 다른 이벤트 수행 중 |
INVALID_COMMAND |
지원하지 않는 명령 |
DEVICE_ERROR |
차량 또는 제어 장치 오류 |
diorama/autonomouscar/{car_id}/status
CAR1 ~ CAR4는 각각 독립적으로 자신의 상태 정보를 Orchestration Server로 송신한다.
| 필드 | 타입 | 데이터 출처 | 설명 |
|---|---|---|---|
vehicle_id |
string | System |
CAR1 ~ CAR4
|
status |
string | System |
IDLE, DRIVING, STOPPED, ARRIVED, ERROR
|
autopilot |
boolean | System | 자율주행 활성화 여부 |
speed |
number | Vehicle/Simulation | 현재 속도 km/h
|
battery |
number | Vehicle/Simulation | 차량 배터리 %
|
traffic |
string | Simulation |
LOW, NORMAL, HIGH
|
current_position |
string | System/Simulation | 현재 위치 |
destination |
string | System | 목적지 |
progress |
number | Simulation | 이동 진행률 %
|
estimated_time |
number | Simulation | 목적지까지 예상 시간(sec) |
distance_remaining |
number | Simulation | 잔여 거리 |
climate_control |
boolean | Simulation | 공조 시스템 동작 여부 |
event_led |
string | Arduino | Station 이벤트 LED |
destination_reached |
boolean | System | 목적지 도착 여부 |
scenario_id |
string | System | Scenario ID |
timestamp |
string | System | 데이터 생성 시간 |
{
"vehicle_id": "CAR1",
"status": "DRIVING",
"autopilot": true,
"speed": 32.5,
"battery": 78,
"traffic": "NORMAL",
"current_position": "ROAD_A",
"destination": "HYDROGEN_CENTER",
"progress": 62,
"estimated_time": 35,
"distance_remaining": 1.8,
"climate_control": true,
"event_led": "GREEN",
"destination_reached": false,
"scenario_id": "SCN-AUTO-001",
"timestamp": "2026-09-29T08:40:10+09:00"
}| 항목 | 설정 |
|---|---|
| REQUEST QoS | 1 |
| RESPONSE QoS | 1 |
| STATUS QoS | 1 |
| REQUEST Retain | false |
| RESPONSE Retain | false |
| STATUS Retain | true |
| Payload | JSON |
| Encoding | UTF-8 |
| Vehicle | CAR1 ~ CAR4 |
| Traffic Data | Simulation |
| Speed | Vehicle/Simulation |
| Battery | Vehicle/Simulation |
위 다섯 구역 명세를 서버가 어떻게 받아 쓰는지. 허브 팀이 문서를 고치면 서버도 여기를 보고 따라간다.
| 항목 | 서버 동작 |
|---|---|
| 구역 정의 |
internal/mqttx/hub_catalog.go 가 target·슬러그·command·payload 표를 들고 있고, 백오피스는 GET /api/admin/hub/catalog 로 같은 표를 받아 입력 폼을 만든다 |
| 큐 | 구역마다 따로 (hub:{슬러그}). 드론이 배송하는 동안 트리 LED 를 켤 수 있고, 같은 구역 안에서는 순서가 지켜진다 |
scenario_id |
비어 있으면 서버가 uuid 를 만들어 채운다. 응답 매칭 키가 (session_id, scenario_id, command) 라, 비워 두면 같은 세션의 같은 command 두 건이 같은 키가 된다 |
payload |
문서상 필수 object 라, 보낼 값이 없으면 {} 를 보낸다 |
target |
옛 이름(NEURAL_TREE·FACTORY·DRONE_STATION 등)도 계속 받아 정식 값으로 바꿔 발행한다 |
result |
SUCCESS 만 성공으로 치고 나머지는 실패로 종결한다. 다만 FAILED·BUSY·INVALID_COMMAND·DEVICE_ERROR 를 뭉개지 않고 그대로 실행 로그와 화면에 남긴다 — 스태프가 할 일이 다르기 때문이다. 옛 FAIL 도 받는다 |
응답 payload
|
구역마다 필드가 달라 서버는 해석하지 않고 원문 그대로 로그·화면에 남긴다 |
| 태블릿 전달 (hub_mode, 149·150) | 서버가 받은 diorama/{device}/status 를 orchestration/diorama/{device}/status 로 그대로 릴레이한다(mirror, 기본). app_settings.hub_mode를 simulate 로 바꾸면, hub 자동화 액션을 발행하는 시점에 어드민이 백오피스(GET·PUT·DELETE /api/admin/hub/simulated-responses)에 미리 저장해 둔 (target, command) → 상태 JSON을 그대로 같은 토픽으로 즉시 내보낸다 — 허브 하드웨어가 불안정해 실제 응답이 오지 않아도 태블릿 화면은 멈추지 않는다. 저장된 조합이 없으면 simulate 라도 아무 것도 보내지 않는다. 가상 응답을 저장해 둔 장치(target)는 simulate 에서 실제 허브 status 를 릴레이하지 않는다 — 허브가 2초마다 보내는 실제 상태가 가상 상태를 덮어써서(2026-10-09). 저장하지 않은 장치는 simulate 여도 실제 상태를 그대로 릴레이한다 |
status의connection은online/offline로 보내주세요. 백오피스가 이 값으로 브리지 프로세스의 생사(LWT)를 판정합니다. Arduino 연결 여부는serial(connected/disconnected) 필드로 따로 봅니다 — 문서 6절 표의 "Arduino 연결 상태" 는 이serial에 해당합니다.
- Google ADK 검토 (프레임워크·모델 비교)
- 페르소나 + 상황 카드 모델 (2차 시나리오 구동 방식)
- Mac Studio 로컬 LLM + Claude Opus 하이브리드 라우팅 전략
- 개발 일정·할 일 점검표 (단계별 진행 점검)
- 로봇 Adapter 개발 온보딩 (HA·MQTT 계정 등록, 토픽 적용, 테스트 송수신, 상태 확인)
- LG ThinQ 가전 연동 (HA 통합 · REST 데이터 취득 · 제어)
- 장소 도착 자동화 (태스크/이벤트/장소 규칙 → SPOT·로봇팔·반려로봇·Hub 자동 명령)
- 엔딩 화면 데이터 출처 점검 (차량 3필드 · 세션 종료 엔딩 5화면)