# pos_settings_dialog.py # POS 영수증 프린터 설정 다이얼로그 from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QFormLayout, QMessageBox ) from PyQt5.QtCore import Qt import json import os import socket import time class POSSettingsDialog(QDialog): """POS 영수증 프린터 설정""" def __init__(self, parent=None): super().__init__(parent) self.config_path = os.path.join(os.path.dirname(__file__), '..', 'config.json') self.setWindowTitle("POS 영수증 프린터 설정") self.setMinimumSize(500, 300) self.init_ui() self.load_settings() def init_ui(self): layout = QVBoxLayout() # 제목 title = QLabel("POS 영수증 프린터 설정") title.setStyleSheet("font-size: 16px; font-weight: bold; margin-bottom: 10px;") layout.addWidget(title) # 설명 desc = QLabel("ESC/POS 프로토콜을 지원하는 영수증 프린터 설정\n올댓포스 AGENT가 설치된 PC IP를 입력하세요") desc.setStyleSheet("color: gray; margin-bottom: 20px;") layout.addWidget(desc) # 폼 레이아웃 form_layout = QFormLayout() # IP 주소 self.ip_input = QLineEdit() self.ip_input.setPlaceholderText("예: 192.168.0.174") form_layout.addRow("IP 주소 *", self.ip_input) # 포트 self.port_input = QLineEdit() self.port_input.setText("9100") form_layout.addRow("포트", self.port_input) # 프린터 이름 self.name_input = QLineEdit() self.name_input.setPlaceholderText("예: 메인 POS 프린터") form_layout.addRow("프린터 이름", self.name_input) layout.addLayout(form_layout) layout.addStretch() # 버튼들 button_layout = QHBoxLayout() self.test_button = QPushButton("테스트 인쇄") self.test_button.clicked.connect(self.test_print) self.test_button.setStyleSheet(""" QPushButton { background-color: #2196F3; color: white; padding: 8px 16px; border: none; border-radius: 4px; font-weight: bold; } QPushButton:hover { background-color: #1976D2; } """) button_layout.addWidget(self.test_button) button_layout.addStretch() self.cancel_button = QPushButton("취소") self.cancel_button.clicked.connect(self.reject) button_layout.addWidget(self.cancel_button) self.save_button = QPushButton("저장") self.save_button.clicked.connect(self.save_settings) self.save_button.setStyleSheet(""" QPushButton { background-color: #4CAF50; color: white; padding: 8px 16px; border: none; border-radius: 4px; font-weight: bold; } QPushButton:hover { background-color: #45a049; } """) button_layout.addWidget(self.save_button) layout.addLayout(button_layout) self.setLayout(layout) def load_settings(self): """설정 불러오기""" try: if os.path.exists(self.config_path): with open(self.config_path, 'r', encoding='utf-8') as f: config = json.load(f) pos_config = config.get('pos_printer', {}) self.ip_input.setText(pos_config.get('ip', '')) self.port_input.setText(str(pos_config.get('port', 9100))) self.name_input.setText(pos_config.get('name', '')) except Exception as e: print(f"[POS Settings] 설정 로드 오류: {e}") def save_settings(self): """설정 저장""" ip = self.ip_input.text().strip() port = self.port_input.text().strip() name = self.name_input.text().strip() # 유효성 검사 if not ip: QMessageBox.warning(self, "입력 오류", "IP 주소를 입력해주세요.") return try: port_num = int(port) except ValueError: QMessageBox.warning(self, "입력 오류", "포트는 숫자여야 합니다.") return # 설정 저장 try: config = {} if os.path.exists(self.config_path): with open(self.config_path, 'r', encoding='utf-8') as f: config = json.load(f) config['pos_printer'] = { 'ip': ip, 'port': port_num, 'name': name if name else f"POS Printer ({ip})" } with open(self.config_path, 'w', encoding='utf-8') as f: json.dump(config, f, indent=4, ensure_ascii=False) QMessageBox.information(self, "성공", "POS 프린터 설정이 저장되었습니다.") self.accept() except Exception as e: QMessageBox.warning(self, "오류", f"설정 저장 실패: {str(e)}") def test_print(self): """테스트 인쇄""" ip = self.ip_input.text().strip() port = self.port_input.text().strip() if not ip: QMessageBox.warning(self, "입력 오류", "IP 주소를 입력해주세요.") return try: port_num = int(port) except ValueError: QMessageBox.warning(self, "입력 오류", "포트는 숫자여야 합니다.") return # ESC/POS 테스트 인쇄 try: # ESC/POS 명령어 ESC = b'\x1b' INIT = ESC + b'@' # 프린터 초기화 CUT = ESC + b'd\x03' # 용지 커트 # 테스트 메시지 message = f""" ================================ POS 프린터 테스트! ================================ IP: {ip} Port: {port_num} Time: {time.strftime('%Y-%m-%d %H:%M:%S')} ESC/POS 명령으로 인쇄됨 정상 작동 확인! ================================ """ # EUC-KR 인코딩 (한글 지원) message_bytes = message.encode('euc-kr') command = INIT + message_bytes + b'\n\n\n' + CUT # TCP 소켓으로 전송 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect((ip, port_num)) sock.sendall(command) sock.close() QMessageBox.information( self, "성공", f"테스트 인쇄 명령을 전송했습니다!\n\n" f"IP: {ip}:{port_num}\n\n" f"POS 프린터에서 영수증 출력을 확인하세요." ) except socket.timeout: QMessageBox.warning(self, "실패", f"연결 시간 초과\n\n프린터가 켜져있는지 확인하세요.") except ConnectionRefusedError: QMessageBox.warning(self, "실패", f"연결 거부됨\n\nIP 주소와 포트를 확인하세요.") except UnicodeEncodeError: QMessageBox.warning(self, "인코딩 오류", "EUC-KR로 인코딩할 수 없는 문자가 있습니다.") except Exception as e: QMessageBox.warning(self, "실패", f"테스트 인쇄 실패\n\n{type(e).__name__}: {str(e)}")