"""PAAI ESC/POS 프린터 CLI - EUC-KR 텍스트 방식""" import sys import json import socket from datetime import datetime # 프린터 설정 PRINTER_IP = "192.168.0.174" PRINTER_PORT = 9100 # ESC/POS 명령어 ESC = b'\x1b' INIT = ESC + b'@' # 프린터 초기화 CUT = ESC + b'd\x03' # 피드 + 커트 def print_raw(data: bytes) -> bool: """바이트 데이터를 프린터로 전송""" try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) sock.connect((PRINTER_IP, PRINTER_PORT)) sock.sendall(data) sock.close() return True except Exception as e: print(f"프린터 오류: {e}", file=sys.stderr) return False def wrap_text(text: str, width: int = 44) -> list: """텍스트 줄바꿈 (44자 기준, 들여쓰기 고려)""" if not text: return [] lines = [] words = text.split() current = "" for word in words: if len(current) + len(word) + 1 <= width: current = current + " " + word if current else word else: if current: lines.append(current) current = word if current: lines.append(current) return lines if lines else [text[:width]] def center_text(text: str, width: int = 48) -> str: """중앙 정렬""" text_len = len(text) if text_len >= width: return text spaces = (width - text_len) // 2 return " " * spaces + text def format_paai_receipt(pre_serial: str, patient_name: str, analysis: dict, kims_summary: dict) -> str: """PAAI 복약안내 영수증 텍스트 생성 (48자 기준)""" LINE = "=" * 48 THIN = "-" * 48 now = datetime.now().strftime("%Y-%m-%d %H:%M") # 헤더 msg = f"\n{LINE}\n" msg += center_text("[ PAAI 복약안내 ]") + "\n" msg += f"{LINE}\n" # 환자 정보 msg += f"환자: {patient_name}\n" msg += f"처방번호: {pre_serial}\n" msg += f"출력: {now}\n" msg += f"{THIN}\n" # 상호작용 요약 interaction_count = kims_summary.get('interaction_count', 0) has_severe = kims_summary.get('has_severe', False) if has_severe: msg += "[!!] 중증 상호작용 있음!\n" elif interaction_count > 0: msg += f"[!] 약물 상호작용: {interaction_count}건\n" else: msg += "[V] 상호작용 없음\n" msg += "\n" # 처방 해석 insight = analysis.get('prescription_insight', '') if insight: msg += f"{THIN}\n" msg += ">> 처방 해석\n" for line in wrap_text(insight, 44): msg += f" {line}\n" msg += "\n" # 복용 주의사항 cautions = analysis.get('cautions', []) if cautions: msg += f"{THIN}\n" msg += ">> 복용 주의사항\n" for i, caution in enumerate(cautions[:4], 1): # 첫 줄 first_line = True for line in wrap_text(f"{i}. {caution}", 44): if first_line: msg += f" {line}\n" first_line = False else: msg += f" {line}\n" msg += "\n" # 상담 포인트 counseling = analysis.get('counseling_points', []) if counseling: msg += f"{THIN}\n" msg += ">> 상담 포인트\n" for i, point in enumerate(counseling[:3], 1): first_line = True for line in wrap_text(f"{i}. {point}", 44): if first_line: msg += f" {line}\n" first_line = False else: msg += f" {line}\n" msg += "\n" # OTC 추천 otc_recs = analysis.get('otc_recommendations', []) if otc_recs: msg += f"{THIN}\n" msg += ">> OTC 추천\n" for rec in otc_recs[:2]: product = rec.get('product', '') reason = rec.get('reason', '') msg += f" - {product}\n" for line in wrap_text(reason, 42): msg += f" {line}\n" msg += "\n" # 푸터 msg += f"{LINE}\n" msg += center_text("양구청춘약국 PAAI") + "\n" msg += center_text("Tel: 033-481-5222") + "\n" msg += "\n" return msg def print_paai_receipt(data: dict) -> bool: """PAAI 영수증 인쇄""" try: pre_serial = data.get('pre_serial', '') patient_name = data.get('patient_name', '') analysis = data.get('analysis', {}) kims_summary = data.get('kims_summary', {}) # 텍스트 생성 message = format_paai_receipt(pre_serial, patient_name, analysis, kims_summary) # EUC-KR 인코딩 (한글 지원) text_bytes = message.encode('euc-kr', errors='replace') # 명령어 조합 command = INIT + text_bytes + b'\n\n\n' + CUT return print_raw(command) except Exception as e: print(f"인쇄 오류: {e}", file=sys.stderr) return False def main(): if len(sys.argv) < 2: print("사용법: python paai_printer_cli.py ", file=sys.stderr) sys.exit(1) json_path = sys.argv[1] try: with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) if print_paai_receipt(data): print("인쇄 완료") sys.exit(0) else: sys.exit(1) except Exception as e: print(f"오류: {e}", file=sys.stderr) sys.exit(1) if __name__ == '__main__': main()