feat: ubisam-ppt-make and ubisam-deliverables PPTX integration (Step 2/2) - SW 설계서 자동 생성
- build_02설계_pptx.py 추가: 2.설계 산출물(기능명세·시퀀스·신호정의·IO맵·TactTime) → SW_설계서.pptx 22슬라이드 한 줄 재생산 - cover / history / agenda / divider × 5 / table × 12 / flow × 2 / closing 구성 - tempfile spec JSON → build_deck.py → pptx, spec 자동 삭제 - 실행: set PYTHONUTF8=1 && py .claude/skills/ubisam-deliverables/references/build_02설계_pptx.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f7bacb90c1
commit
0cddd5d5b3
322
.claude/skills/ubisam-deliverables/references/build_02설계_pptx.py
Normal file
322
.claude/skills/ubisam-deliverables/references/build_02설계_pptx.py
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
ILSOS PrismaticRD PTOP — 2.설계 SW_설계서.pptx 자동 생성 스크립트.
|
||||||
|
|
||||||
|
실행:
|
||||||
|
set PYTHONUTF8=1 && py .claude/skills/ubisam-deliverables/references/build_02설계_pptx.py
|
||||||
|
|
||||||
|
출력: docs/[Ubisam산출물]/02.설계/설계리뷰_DR/SW_설계서.pptx
|
||||||
|
"""
|
||||||
|
import os, json, subprocess, sys, tempfile
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
REPO = os.path.abspath(os.path.join(HERE, "..", "..", "..", ".."))
|
||||||
|
BUILDER = os.path.join(REPO, ".claude", "skills", "ubisam-ppt-make", "build_deck.py")
|
||||||
|
OUTPUT = os.path.join(REPO, "docs", "[Ubisam산출물]", "02.설계", "설계리뷰_DR", "SW_설계서.pptx")
|
||||||
|
|
||||||
|
SPEC = {
|
||||||
|
"doc_title": "ILSOS PrismaticRD PTOP SW 설계서",
|
||||||
|
"slides": [
|
||||||
|
{
|
||||||
|
"type": "cover",
|
||||||
|
"tag": "SW DESIGN DOCUMENT",
|
||||||
|
"title": "ILSOS PrismaticRD PTOP\nSW 설계서",
|
||||||
|
"subtitles": [
|
||||||
|
"LGES OC5 PtoP Welder — Prismatic 전지 점 용접 자동화 SW",
|
||||||
|
"Aurora 2.0 / .NET 4.8.1 / WPF · MX Component · ACS EtherCAT · Ajin IO"
|
||||||
|
],
|
||||||
|
"team": "로봇자동화사업부",
|
||||||
|
"contacts": ["노도연 대리 otteryeonny@ubisam.com"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "history",
|
||||||
|
"no": "00.",
|
||||||
|
"title": "변경 이력",
|
||||||
|
"subtitle": "Revision History",
|
||||||
|
"rows": [
|
||||||
|
["01", "0.1", "2026-06-29", "노도연", "소스 기반 최초 작성 (기능명세·시퀀스·신호정의·IO맵·TactTime)"],
|
||||||
|
["02", "0.2", "2026-06-30", "노도연", "SW_설계서.pptx 최초 생성 (build_02설계_pptx.py)"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "agenda",
|
||||||
|
"title": "Contents",
|
||||||
|
"subtitle": "목차",
|
||||||
|
"items": [
|
||||||
|
{"no": "01", "title": "기능명세서", "sub": "메뉴 구조 · View별 기능"},
|
||||||
|
{"no": "02", "title": "제어 시퀀스 / 인터록", "sub": "SeqAutoRunPTOP · 인터록 정의"},
|
||||||
|
{"no": "03", "title": "PLC-PC 신호 정의", "sub": "통신 사양 · PC↔PLC 신호 목록"},
|
||||||
|
{"no": "04", "title": "모션축 / IO 맵", "sub": "축 정의 · DI/DO 맵"},
|
||||||
|
{"no": "05", "title": "TactTime 산정서", "sub": "자동 1사이클 단위동작별 T/T"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# ── 01. 기능명세서 ──────────────────────────────────────────────
|
||||||
|
{"type": "divider", "no": "01", "title": "기능명세서", "subtitle": "UI / Function Specification"},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "01.", "title": "메뉴 구조",
|
||||||
|
"subtitle": "RegisterViews — 메인 메뉴 · 권한 · 서브뷰 · 기능 요약",
|
||||||
|
"headers": ["메인 메뉴", "권한", "서브뷰", "기능"],
|
||||||
|
"widths": [1.6, 1.2, 3.4, 5.2], "center_cols": [0, 1],
|
||||||
|
"rows": [
|
||||||
|
["AutoRun", "NONE", "UCMainAutoRun", "자동 운전 메인(SeqAutoRun 연동), 페이지/상태 표시"],
|
||||||
|
["Recipe", "NONE", "UCRecipe / UCRecipeChangeHistory / UCModel", "레시피 편집·변경이력·모델"],
|
||||||
|
["Manual", "NONE", "UCManualScannerOperation / UCManualModelFinder", "스캐너 수동조작·모델 파인더"],
|
||||||
|
["Calibration","NONE", "UCScannerCalibration / UCCameraPixelResolution", "스캐너 보정·픽셀 해상도"],
|
||||||
|
["Monitoring", "NONE", "UCPLCBit / UCPLCWord / UCIOInterfaceView", "PLC 비트(M)·워드(D)·IO 모니터링"],
|
||||||
|
["Device", "LEVEL3", "DeviceSettingView", "디바이스 설정"],
|
||||||
|
["Setting", "LEVEL1", "EquipSettingView / LogSettingView / AutoBackupView2", "장비·로그·자동백업 설정"],
|
||||||
|
["Alarm", "NONE", "AlarmHistoryView / AlarmDescView", "알람 이력·설명"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "01.", "title": "View별 기능 (1/2)",
|
||||||
|
"subtitle": "MainView · RecipeView · ManualView",
|
||||||
|
"headers": ["View", "no", "기능 영역", "기능명", "연동"],
|
||||||
|
"widths": [1.6, 0.6, 1.8, 2.8, 4.6], "center_cols": [0, 1],
|
||||||
|
"rows": [
|
||||||
|
["MainView", "1", "운전", "StartSequence / Stop", "SeqAutoRunPTOP"],
|
||||||
|
["MainView", "2", "상태", "UpdatePageNum", "EVENT_AUTO_RUN_UPDATE_PAGENUM"],
|
||||||
|
["MainView", "3", "상태", "WorkingPosition", "eWorkingPosition"],
|
||||||
|
["MainView", "4", "운전", "Auto→Manual+Resume", "bit15(PLC_WELD_READY_REQ)"],
|
||||||
|
["MainView", "5", "표시", "ScannerCanvasCtrlTeaching", "레이어/오브젝트"],
|
||||||
|
["RecipeView", "1", "레시피", "ActivateRecipe", "RecipeManager"],
|
||||||
|
["RecipeView", "2", "레시피", "RecipeChangeHistory", "RchHandler"],
|
||||||
|
["RecipeView", "3", "모델", "UCModel / EquipmentSpecificModel", "EquipmentSpecificModel_PTOP"],
|
||||||
|
["ManualView", "1", "수동", "ScannerOperation", "CommonDeviceIds.Scanner"],
|
||||||
|
["ManualView", "2", "수동", "ModelFinder", "UCManualModelFinder"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "01.", "title": "View별 기능 (2/2)",
|
||||||
|
"subtitle": "MonitoringView · CalibrationView · SettingView · AlarmView",
|
||||||
|
"headers": ["View", "no", "기능 영역", "기능명", "연동"],
|
||||||
|
"widths": [1.8, 0.6, 1.8, 2.8, 4.4], "center_cols": [0, 1],
|
||||||
|
"rows": [
|
||||||
|
["MonitoringView", "1", "모니터링", "PLCBitMonitoring", "ePLCDevice.M"],
|
||||||
|
["MonitoringView", "2", "모니터링", "PLCWordMonitoring", "ePLCDevice.D"],
|
||||||
|
["MonitoringView", "3", "모니터링", "IOInterfaceView", "IODevice"],
|
||||||
|
["CalibrationView", "1", "보정", "UCScannerCalibration", "스캐너 보정"],
|
||||||
|
["CalibrationView", "2", "보정", "UCCameraPixelResolution","카메라 픽셀 해상도"],
|
||||||
|
["SettingView", "1", "설정", "EquipSettingView", "장비 설정"],
|
||||||
|
["SettingView", "2", "설정", "LogSettingView / AutoBackupView2", "로그·자동백업"],
|
||||||
|
["AlarmView", "1", "알람", "AlarmHistoryView", "AlarmCode_PTOP"],
|
||||||
|
["AlarmView", "2", "알람", "AlarmDescView", "AlarmManager_PTOP"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# ── 02. 제어 시퀀스 / 인터록 ────────────────────────────────────
|
||||||
|
{"type": "divider", "no": "02", "title": "제어 시퀀스 / 인터록", "subtitle": "Control Sequence & Interlock"},
|
||||||
|
{
|
||||||
|
"type": "flow",
|
||||||
|
"no": "02.", "title": "SeqAutoRunPTOP — 자동 시퀀스 (초기화 ~ 업로드)",
|
||||||
|
"subtitle": "Sequences/SeqAutoRunPTOP.cs — Builder() 노드 흐름 (1/2)",
|
||||||
|
"steps": [
|
||||||
|
{"title": "Sequence_Enter", "code": "레시피/장비 초기화 · PC_AUTO_STATUS ON", "kind": "proc"},
|
||||||
|
{"title": "CheckInitCondition", "code": "초기 조건 판단", "kind": "dec"},
|
||||||
|
{"title": "CheckPageNo", "code": "PLC_PAGE_CHANGE_REQ(0x08) 대기", "kind": "proc"},
|
||||||
|
{"title": "CheckRecipeNoComp", "code": "PLC_RECIPE_NO 확정/전환 · PC_RECIPE_NO 에코", "kind": "proc"},
|
||||||
|
{"title": "CheckPageNoComp", "code": "PLC_PAGE_NO 3회 검증 · PC_PAGE_CHANGE_COMPLETE ACK", "kind": "proc"},
|
||||||
|
{"title": "SeqUploadWeldingList","code": "레이어 선택 → 용접리스트 업로드 · offset(D70510) 적용", "kind": "proc"}
|
||||||
|
],
|
||||||
|
"branch": {"title": "Resume", "sub": "핸드셰이크 스킵"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "flow",
|
||||||
|
"no": "02.", "title": "SeqAutoRunPTOP — 자동 시퀀스 (발진 ~ 완료)",
|
||||||
|
"subtitle": "Sequences/SeqAutoRunPTOP.cs — Builder() 노드 흐름 (2/2)",
|
||||||
|
"steps": [
|
||||||
|
{"title": "WeldingStartReadBit", "code": "PLC_WELD_TRIGGER_REQ(0x10) 대기", "kind": "proc"},
|
||||||
|
{"title": "PreScoutCheck", "code": "M70509 ON → PreScout 실행", "kind": "dec"},
|
||||||
|
{"title": "WaitWeldingStart", "code": "PC_WELD_TRIGGER_ACK ON / WELD_COMPLETE OFF", "kind": "proc"},
|
||||||
|
{"title": "ExecuteWelding", "code": "HeadTheta 인터락 → Gate ON(15ms) → ExecuteList → Gate OFF", "kind": "proc"},
|
||||||
|
{"title": "WriteWeldComplete", "code": "PC_WELD_TRIGGER_ACK OFF · PC_WELD_COMPLETE ON", "kind": "proc"},
|
||||||
|
{"title": "CheckCycleStop", "code": "루프백 or SaveResult → WriteCompletionPLCBit", "kind": "dec"}
|
||||||
|
],
|
||||||
|
"branch": {"title": "PostScout", "sub": "M70509 ON 시 실행"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "02.", "title": "인터록 정의",
|
||||||
|
"subtitle": "LaserInterlockSetting.cs · SeqAutoRunPTOP.cs",
|
||||||
|
"headers": ["#", "인터록", "조건", "동작"],
|
||||||
|
"widths": [0.5, 2.3, 4.0, 4.6], "center_cols": [0],
|
||||||
|
"rows": [
|
||||||
|
["1", "Head Theta 발진 게이트", "LaserInterlockSetting.HeadThetaInterlockEnabled ON · Front/Down ±tol 벗어남", "발진 차단 (ALARM_LASER_HEAD_THETA_INTERLOCK). PLC 미연결 시 fail-closed"],
|
||||||
|
["2", "레시피별 방향 차단", "RecipeLaserInterlock.Front/Down 체크", "해당 방향 구역이면 발진 차단"],
|
||||||
|
["3", "중알람(Heavy)", "PLC_HEAVY_ALARM_STATUS(0x05)", "AlarmManager_PTOP.StopSequenceByAlarm → 시퀀스 정지"],
|
||||||
|
["4", "Door / EMO", "PLC_DOOR_INTERLOCK(0x06) / PLC_EMO_STATUS(0x07)", "안전 정지"],
|
||||||
|
["5", "업로드 실패", "용접 오브젝트 0개 / Upload Success=false", "시퀀스 중단 (return null)"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# ── 03. PLC-PC 신호 정의서 ──────────────────────────────────────
|
||||||
|
{"type": "divider", "no": "03", "title": "PLC-PC 신호 정의서", "subtitle": "PLC Interface Signal Definition"},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "03.", "title": "통신 사양",
|
||||||
|
"subtitle": "EquipmentSetup.cs · PLCController.Address.cs",
|
||||||
|
"headers": ["항목", "내용"],
|
||||||
|
"widths": [2.8, 8.6], "center_cols": [],
|
||||||
|
"rows": [
|
||||||
|
["PLC 기종", "Mitsubishi Melsec"],
|
||||||
|
["통신 방식", "MX Component (ePLCNetType.MXComponent) — EquipmentSetup.RegisterDevices()"],
|
||||||
|
["맵 파일", "CSV (PLCMMapFileType.CSV)"],
|
||||||
|
["데이터 갱신", "폴링(10ms 주기 ReadBit/ReadWord) + 이벤트 비트(REQ/ACK)"],
|
||||||
|
["디바이스 영역", "비트=M, 워드=D (입력 M70500/D70500 · 출력 M70000/D70000 — 제안)"],
|
||||||
|
["핸드셰이크 규칙", "요청(REQ)→처리→완료(ACK/COMPLETE). 단일 트리거 PLC_PAGE_CHANGE_REQ(0x08)"],
|
||||||
|
["인터락", "Door(0x06)·EMO(0x07)·Heavy알람(0x05) → 시퀀스 정지. HeadTheta(D70510) 발진 게이트"],
|
||||||
|
["Watchdog", "PLC_LIVE_STATUS(0x00) ↔ PC_LIVE_STATUS(0x00) Alive 토글"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "03.", "title": "PC → PLC 신호 목록",
|
||||||
|
"subtitle": "eBitOutput / eWordOutput (Write) — 주요 신호",
|
||||||
|
"headers": ["No", "신호명(enum)", "디바이스", "Type", "의미"],
|
||||||
|
"widths": [0.7, 3.3, 1.4, 0.8, 5.2], "center_cols": [0, 2, 3],
|
||||||
|
"rows": [
|
||||||
|
["0x00", "PC_LIVE_STATUS", "M70000", "BIT", "PC Alive 토글 (Watchdog)"],
|
||||||
|
["0x01", "PC_AUTO_STATUS", "M70001", "BIT", "Auto 상태 — Enter 시 ON"],
|
||||||
|
["0x05", "PC_HEAVY_ALARM_STATUS", "M70005", "BIT", "중알람"],
|
||||||
|
["0x06", "PC_DOOR_INTERLOCK", "M70006", "BIT", "Door 인터락"],
|
||||||
|
["0x07", "PC_EMO_STATUS", "M70007", "BIT", "EMO"],
|
||||||
|
["0x08", "PC_PAGE_CHANGE_COMPLETE", "M70008", "BIT", "페이지 확정 ACK — PageNo 일치 시 ON"],
|
||||||
|
["0x0F", "PC_WELD_READY_ACK", "M70015", "BIT", "Resume ACK (bit15, 260621)"],
|
||||||
|
["0x10", "PC_WELD_TRIGGER_ACK", "M70016", "BIT", "용접 트리거 ACK"],
|
||||||
|
["0x11", "PC_WELD_BUSY", "M70017", "BIT", "Laser On 표시(발진중)"],
|
||||||
|
["0x12", "PC_WELD_COMPLETE", "M70018", "BIT", "용접 완료"],
|
||||||
|
["D0x01", "PC_PAGE_NO", "D70001", "INT", "페이지 번호 에코"],
|
||||||
|
["D0x02", "PC_RECIPE_NO", "D70002", "INT", "레시피 번호 에코"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "03.", "title": "PLC → PC 신호 목록",
|
||||||
|
"subtitle": "eBitInput / eWordInput (Read) — 주요 신호",
|
||||||
|
"headers": ["No", "신호명(enum)", "디바이스", "Type", "의미"],
|
||||||
|
"widths": [0.7, 3.3, 1.4, 0.8, 5.2], "center_cols": [0, 2, 3],
|
||||||
|
"rows": [
|
||||||
|
["0x00", "PLC_LIVE_STATUS", "M70500", "BIT", "PLC Alive (Watchdog)"],
|
||||||
|
["0x05", "PLC_HEAVY_ALARM_STATUS", "M70505", "BIT", "중알람 → 시퀀스 정지"],
|
||||||
|
["0x06", "PLC_DOOR_INTERLOCK", "M70506", "BIT", "Door 인터락"],
|
||||||
|
["0x07", "PLC_EMO_STATUS", "M70507", "BIT", "EMO"],
|
||||||
|
["0x08", "PLC_PAGE_CHANGE_REQ", "M70508", "BIT", "단일 게이트 트리거 — PageNo+RecipeNo 확정"],
|
||||||
|
["0x09", "PLC_SCOUT_ENABLE", "M70509", "BIT", "Scout 상시 ON → 용접 전/후 Scout"],
|
||||||
|
["0x0F", "PLC_WELD_READY_REQ", "M70515", "BIT", "Weld_01 Ready → Resume 트리거 (bit15)"],
|
||||||
|
["0x10", "PLC_WELD_TRIGGER_REQ", "M70516", "BIT", "용접 발진 요청"],
|
||||||
|
["D0x01", "PLC_PAGE_NO", "D70501", "INT", "페이지 번호 (1-base, 3회 검증)"],
|
||||||
|
["D0x02", "PLC_RECIPE_NO", "D70502", "INT", "레시피 번호 (11/21/22/31/32)"],
|
||||||
|
["D0x0A", "HEAD_THETA_POSITION", "D70510", "INT", "Laser1 Head Theta — 발진 인터락"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# ── 04. 모션축 / IO 맵 ──────────────────────────────────────────
|
||||||
|
{"type": "divider", "no": "04", "title": "모션축 / IO 맵", "subtitle": "Motion Axis & I/O Map"},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "04.", "title": "통신·제어 구성",
|
||||||
|
"subtitle": "EquipmentSetup.cs · PAIX_PTOP.cs · architecture.md §4",
|
||||||
|
"headers": ["구분", "대상", "컨트롤러/디바이스", "통신/버스", "수량·범위"],
|
||||||
|
"widths": [1.8, 1.8, 2.8, 2.0, 3.0], "center_cols": [0],
|
||||||
|
"rows": [
|
||||||
|
["PLC통신", "외부 신호 제어", "Mitsubishi Melsec", "MX Component", "1"],
|
||||||
|
["I/O", "디지털 IO", "Ajin(AJINEXTEK)", "필드버스", "DI/DO"],
|
||||||
|
["Laser", "Core/Ring 레이저", "IO Gate(TruPulse nano 계열)", "DO 게이트", "2(Core+Ring)"],
|
||||||
|
["Scanner", "레이저 스캐너", "RTC LaserScanner", "RTC", "1"],
|
||||||
|
["모션(Servo)", "X/Y 축", "ACS SPiiPlus", "EtherCAT", "2축 (제안)"],
|
||||||
|
["모션(Servo)", "Z 축", "Ajin Motion Board", "보드", "1축 (제안)"],
|
||||||
|
["Vision", "카메라/측정", "MIL 기반 AuroraVision", "—", "(현재 미사용)"],
|
||||||
|
["상/하위(MES)", "호스트 연동", "Stream(LBAD/RPC)", "TCP", "옵션"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "04.", "title": "모션축 정의",
|
||||||
|
"subtitle": "ACS SPiiPlus(EtherCAT) · Ajin Motion Board — 파라미터 미확정(제안)",
|
||||||
|
"headers": ["Axis", "축명", "용도", "컨트롤러/통신", "행정/범위", "최대속도", "Home방식"],
|
||||||
|
"widths": [0.7, 0.8, 1.7, 2.5, 1.7, 1.5, 2.5], "center_cols": [0, 1],
|
||||||
|
"rows": [
|
||||||
|
["0", "X", "셀 위치 X", "ACS SPiiPlus / EtherCAT", "(제안)", "(제안)", "(제안)"],
|
||||||
|
["1", "Y", "셀 위치 Y", "ACS SPiiPlus / EtherCAT", "(제안)", "(제안)", "(제안)"],
|
||||||
|
["2", "Z", "포커스/높이", "Ajin Motion Board", "(제안)", "(제안)", "(제안)"],
|
||||||
|
["—", "Scanner θ/XY", "빔 편향(갈바노)", "RTC LaserScanner", "List 기반 Jump/Mark", "—", "보정테이블"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "04.", "title": "I/O 맵 — DI / DO",
|
||||||
|
"subtitle": "PAIX_PTOP.ePrismaticDIAddress / ePrismaticDOAddress (Ajin 필드버스)",
|
||||||
|
"headers": ["구분", "CH(No)", "신호명", "Active", "설명"],
|
||||||
|
"widths": [0.8, 1.0, 3.2, 1.0, 5.4], "center_cols": [0, 1, 3],
|
||||||
|
"rows": [
|
||||||
|
["DI", "9", "CoreLaser_Laser_Ready", "High", "Core 레이저 Ready"],
|
||||||
|
["DI", "10", "CoreLaser_Error_State", "High", "Core 레이저 에러"],
|
||||||
|
["DI", "11", "CoreLaser_Laser_Output_State", "High", "Core 발진 출력 상태"],
|
||||||
|
["DI", "12", "CoreLaser_Control_Status", "High", "Core 제어 상태"],
|
||||||
|
["DI", "13", "RingLaser_Laser_Ready", "High", "Ring 레이저 Ready"],
|
||||||
|
["DI", "14", "RingLaser_Error_State", "High", "Ring 레이저 에러"],
|
||||||
|
["DI", "15", "RingLaser_Laser_Output_State", "High", "Ring 발진 출력 상태"],
|
||||||
|
["DI", "23", "RingLaser_Control_Status", "High", "Ring 제어 상태"],
|
||||||
|
["DO", "9", "CoreLaser_Control", "High", "Core 레이저 게이트(발진 ON/OFF)"],
|
||||||
|
["DO", "10", "CoreLaser_ErrorClearing", "High", "Core 에러 클리어"],
|
||||||
|
["DO", "13", "RingLaser_Control", "High", "Ring 레이저 게이트(발진 ON/OFF)"],
|
||||||
|
["DO", "14", "RingLaser_ErrorClearing", "High", "Ring 에러 클리어"],
|
||||||
|
["DO", "17", "EX_Red_Control", "High", "EX Red(가이드/표시등) 제어"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# ── 05. TactTime 산정서 ─────────────────────────────────────────
|
||||||
|
{"type": "divider", "no": "05", "title": "TactTime 산정서", "subtitle": "Tact Time Analysis"},
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"no": "05.", "title": "PC TactTime — 자동 1사이클 (음극 1페이지 기준)",
|
||||||
|
"subtitle": "SeqAutoRunPTOP.cs 지연·로그 상수 기준 (제안 — 현장 실측 시 확정)",
|
||||||
|
"headers": ["Unit", "단위동작", "T/T(ms)", "PC", "PLC", "출처"],
|
||||||
|
"widths": [0.7, 3.0, 1.3, 0.6, 0.6, 5.2], "center_cols": [0, 2, 3, 4],
|
||||||
|
"rows": [
|
||||||
|
["1", "Page Change 요청 대기", "가변", "●", "●", "CheckPageNo (폴링 10ms, timeout 60s)"],
|
||||||
|
["2", "Recipe 확정/전환", "~0~수백","●", "—", "CheckRecipeNoComp (동일이면 ~0, 전환 시 Activate+reload)"],
|
||||||
|
["3", "Page 3회 검증", "~600", "●", "●", "CheckPageNoComp (200ms×3)"],
|
||||||
|
["4", "용접리스트 업로드", "가변", "●", "—", "SeqUploadWeldingList (라인수 의존)"],
|
||||||
|
["5", "발진 요청 대기", "가변", "●", "●", "WeldingStartReadBit"],
|
||||||
|
["6", "준비 응답", "~205", "●", "●", "WaitWeldingStart (200+5ms)"],
|
||||||
|
["7", "Gate ON delay", "15", "●", "—", "laserEmissionGateDelayMs (TruPulse 매뉴얼 ≥10ms)"],
|
||||||
|
["8", "실제 발진(ExecuteList)", "~285", "—", "—", "로그 예시 'TactTime: [285ms]' (라인수 의존)"],
|
||||||
|
["9", "Gate OFF + BUSY OFF", "~50", "●", "—", "ExecuteWelding 후미"],
|
||||||
|
["10", "Jump+CorrectionTable 복귀", "~500", "—", "—", "Thread.Sleep(500)"],
|
||||||
|
["11", "완료비트 송신", "~55", "●", "●", "WriteWeldComplete (50+5ms)"],
|
||||||
|
["(옵션)","Pre/Post Scout", "+100/회","●","Vision","SCOUT_PROCEED_DELAY_MS, M70509 ON 시"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "closing",
|
||||||
|
"title": "Thank You",
|
||||||
|
"message": "본 설계서는 소스코드 분석 기반 0.2버전입니다. 파라미터 확정 후 갱신 예정.",
|
||||||
|
"team": "로봇자동화사업부",
|
||||||
|
"contacts": ["노도연 대리 otteryeonny@ubisam.com"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
|
||||||
|
fd, spec_path = tempfile.mkstemp(suffix=".json", prefix="sw_spec_")
|
||||||
|
try:
|
||||||
|
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(SPEC, f, ensure_ascii=False, indent=2)
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, BUILDER, "--input", spec_path, "--output", OUTPUT],
|
||||||
|
capture_output=True, text=True, encoding="utf-8"
|
||||||
|
)
|
||||||
|
if result.stdout:
|
||||||
|
print(result.stdout.strip())
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("[ERROR]", result.stderr.strip(), file=sys.stderr)
|
||||||
|
sys.exit(result.returncode)
|
||||||
|
finally:
|
||||||
|
if os.path.exists(spec_path):
|
||||||
|
os.remove(spec_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user