183 lines
7.2 KiB
Python
183 lines
7.2 KiB
Python
import json
|
|
import os
|
|
|
|
from PyQt5.QtWidgets import QWidget, QLabel, QProgressBar, QVBoxLayout, QApplication
|
|
from PyQt5.QtCore import Qt, QThread, pyqtSignal
|
|
from PyQt5.QtGui import QPainter, QPainterPath, QColor
|
|
|
|
|
|
class SplashScreen(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
|
self.setAttribute(Qt.WA_TranslucentBackground)
|
|
self.setFixedSize(500, 300)
|
|
|
|
screen = QApplication.primaryScreen().geometry()
|
|
self.move(
|
|
(screen.width() - self.width()) // 2,
|
|
(screen.height() - self.height()) // 2,
|
|
)
|
|
self._build_ui()
|
|
|
|
def _build_ui(self):
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(40, 40, 40, 30)
|
|
layout.setSpacing(0)
|
|
|
|
title = QLabel("리플렉터 검사 시스템")
|
|
title.setAlignment(Qt.AlignCenter)
|
|
title.setStyleSheet(
|
|
"color:#ffffff; font-size:22px; font-weight:bold; background:transparent;"
|
|
)
|
|
|
|
subtitle = QLabel("Reflector Inspection System")
|
|
subtitle.setAlignment(Qt.AlignCenter)
|
|
subtitle.setStyleSheet("color:#555555; font-size:12px; background:transparent;")
|
|
|
|
layout.addStretch(2)
|
|
layout.addWidget(title)
|
|
layout.addSpacing(6)
|
|
layout.addWidget(subtitle)
|
|
layout.addStretch(3)
|
|
|
|
self.status_label = QLabel("초기화 중...")
|
|
self.status_label.setAlignment(Qt.AlignCenter)
|
|
self.status_label.setStyleSheet(
|
|
"color:#888888; font-size:13px; background:transparent;"
|
|
)
|
|
layout.addWidget(self.status_label)
|
|
layout.addSpacing(10)
|
|
|
|
self.progress_bar = QProgressBar()
|
|
self.progress_bar.setRange(0, 100)
|
|
self.progress_bar.setValue(0)
|
|
self.progress_bar.setFixedHeight(6)
|
|
self.progress_bar.setTextVisible(False)
|
|
self.progress_bar.setStyleSheet("""
|
|
QProgressBar {
|
|
background: #2a2a2a;
|
|
border: none;
|
|
border-radius: 3px;
|
|
}
|
|
QProgressBar::chunk {
|
|
background: #1D9E75;
|
|
border-radius: 3px;
|
|
}
|
|
""")
|
|
layout.addWidget(self.progress_bar)
|
|
layout.addStretch(1)
|
|
|
|
version = QLabel("v1.0.0")
|
|
version.setAlignment(Qt.AlignCenter)
|
|
version.setStyleSheet("color:#333333; font-size:11px; background:transparent;")
|
|
layout.addWidget(version)
|
|
|
|
def update_progress(self, value: int, message: str):
|
|
self.progress_bar.setValue(value)
|
|
self.status_label.setText(message)
|
|
QApplication.processEvents()
|
|
|
|
def paintEvent(self, event):
|
|
painter = QPainter(self)
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
path = QPainterPath()
|
|
path.addRoundedRect(0.0, 0.0, float(self.width()), float(self.height()), 12.0, 12.0)
|
|
painter.fillPath(path, QColor("#0d0d0d"))
|
|
|
|
|
|
class InitWorker(QThread):
|
|
progress = pyqtSignal(int, str) # (진행률, 메시지)
|
|
finished = pyqtSignal(object) # 초기화 결과 dict
|
|
|
|
def run(self):
|
|
from utils.path_helper import get_path
|
|
from camera.insight import InSightCamera
|
|
from camera.basler import BaslerCamera
|
|
from ai.detector import Detector
|
|
from db.sql_client import SQLClient
|
|
|
|
results = {}
|
|
|
|
# ── 1단계: 설정 로드 ──────────────────────────────────────────── #
|
|
self.progress.emit(10, "설정 불러오는 중...")
|
|
try:
|
|
with open(get_path("config.json"), encoding="utf-8") as f:
|
|
config = json.load(f)
|
|
except Exception as e:
|
|
print(f"[InitWorker] 설정 로드 실패: {e}")
|
|
config = {}
|
|
results["config"] = config
|
|
|
|
# ── 2단계: 코그넥스 카메라 ────────────────────────────────────── #
|
|
self.progress.emit(25, "코그넥스 카메라 연결 중...")
|
|
insight = InSightCamera()
|
|
try:
|
|
cognex_cfg = config.get("cognex", {})
|
|
ip = cognex_cfg.get("ip", "")
|
|
port = cognex_cfg.get("port", 23)
|
|
if ip:
|
|
insight.connect(ip, port)
|
|
except Exception as e:
|
|
print(f"[InitWorker] 코그넥스 연결 실패: {e}")
|
|
results["insight"] = insight
|
|
|
|
# ── 3단계: Basler 카메라 ──────────────────────────────────────── #
|
|
self.progress.emit(45, "Basler 카메라 연결 중...")
|
|
basler = BaslerCamera()
|
|
try:
|
|
basler.connect()
|
|
except Exception as e:
|
|
print(f"[InitWorker] Basler 연결 실패: {e}")
|
|
results["basler"] = basler
|
|
|
|
# ── 4단계: AI 모델 로드 ───────────────────────────────────────── #
|
|
self.progress.emit(65, "AI 모델 로드 중...")
|
|
detector = Detector()
|
|
try:
|
|
from paths import resolve_path
|
|
model_path = config.get("ai", {}).get("model_path", "")
|
|
if model_path:
|
|
abs_path = resolve_path(model_path)
|
|
if abs_path and os.path.exists(abs_path):
|
|
detector.load_model(abs_path)
|
|
except Exception as e:
|
|
print(f"[InitWorker] AI 모델 로드 실패: {e}")
|
|
results["detector"] = detector
|
|
|
|
# ── 5단계: DB 연결 ────────────────────────────────────────────── #
|
|
self.progress.emit(80, "DB 연결 중...")
|
|
db_client = SQLClient()
|
|
try:
|
|
db_cfg = config.get("db", {})
|
|
if db_cfg.get("server"):
|
|
db_client.connect(
|
|
db_cfg["server"],
|
|
db_cfg["database"],
|
|
db_cfg["username"],
|
|
db_cfg["password"],
|
|
)
|
|
except Exception as e:
|
|
print(f"[InitWorker] DB 연결 실패: {e}")
|
|
results["db"] = db_client
|
|
|
|
# ── 6단계: PLC 연결 ───────────────────────────────────────────── #
|
|
self.progress.emit(92, "PLC 연결 중...")
|
|
plc_client = None
|
|
try:
|
|
from plc.plc_client import PLCClient
|
|
plc_cfg = config.get("plc", {})
|
|
ip = plc_cfg.get("ip", "").strip()
|
|
port = plc_cfg.get("port", 5010)
|
|
if ip:
|
|
client = PLCClient()
|
|
if client.connect(ip, port):
|
|
plc_client = client
|
|
except Exception as e:
|
|
print(f"[InitWorker] PLC 연결 실패: {e}")
|
|
results["plc"] = plc_client
|
|
|
|
# ── 완료 ──────────────────────────────────────────────────────── #
|
|
self.progress.emit(100, "시작 중...")
|
|
self.finished.emit(results)
|