""" ESC/POS QR 코드 인쇄 방식 테스트 v2 더 많은 변형 시도 (크기, 밀도, 파라미터) """ import socket import qrcode import time # 프린터 설정 PRINTER_IP = "192.168.0.174" PRINTER_PORT = 9100 # 테스트 URL (더 짧게) TEST_URL = "https://bit.ly/test" def send_to_printer(data, method_name): """프린터로 데이터 전송""" try: print(f"\n[{method_name}] 전송 중... ({len(data)} bytes)") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) sock.connect((PRINTER_IP, PRINTER_PORT)) sock.sendall(data) sock.close() print(f"[{method_name}] ✅ 완료") time.sleep(1.5) return True except Exception as e: print(f"[{method_name}] ❌ 실패: {e}") return False def method_1_tiny_qr_escstar(): """방법 1: 아주 작은 QR (30x30) + ESC *""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 1 ***\n".encode('euc-kr')) commands.append(" 작은 QR 30x30 (ESC *)\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) # 30x30 QR qr = qrcode.QRCode(version=1, box_size=1, border=1) qr.add_data(TEST_URL) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white").resize((30, 30)).convert('1') width, height = img.size pixels = img.load() # ESC * m=0 (8-dot single-density) for y in range(0, height, 8): commands.append(ESC + b'*' + bytes([0, width & 0xFF, (width >> 8) & 0xFF])) for x in range(width): byte = 0 for bit in range(min(8, height - y)): if pixels[x, y + bit] == 0: byte |= (1 << (7 - bit)) commands.append(bytes([byte])) commands.append(b'\n') commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def method_2_medium_qr_escstar_mode32(): """방법 2: 중간 QR (50x50) + ESC * mode 32""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 2 ***\n".encode('euc-kr')) commands.append(" 중간 QR 50x50 (ESC * m=32)\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) # 50x50 QR qr = qrcode.QRCode(version=1, box_size=2, border=1) qr.add_data(TEST_URL) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white").resize((50, 50)).convert('1') width, height = img.size pixels = img.load() # ESC * m=32 (24-dot single-density) for y in range(0, height, 24): commands.append(ESC + b'*' + bytes([32, width & 0xFF, (width >> 8) & 0xFF])) for x in range(width): byte1 = byte2 = byte3 = 0 for bit in range(min(24, height - y)): if pixels[x, y + bit] == 0: if bit < 8: byte1 |= (1 << (7 - bit)) elif bit < 16: byte2 |= (1 << (15 - bit)) else: byte3 |= (1 << (23 - bit)) commands.append(bytes([byte1, byte2, byte3])) commands.append(b'\n') commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def method_3_native_qr_simple(): """방법 3: 내장 QR (더 간단한 설정)""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 3 ***\n".encode('euc-kr')) commands.append(" 내장 QR 간단 설정\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) qr_data = TEST_URL.encode('utf-8') data_len = len(qr_data) + 3 # Model 2 commands.append(GS + b'(k' + bytes([3, 0, 49, 65, 50])) # Error correction L commands.append(GS + b'(k' + bytes([3, 0, 49, 69, 48])) # Size 4 commands.append(GS + b'(k' + bytes([3, 0, 49, 67, 4])) # Store data commands.append(GS + b'(k' + bytes([data_len & 0xFF, (data_len >> 8) & 0xFF, 49, 80, 48]) + qr_data) # Print commands.append(GS + b'(k' + bytes([3, 0, 49, 81, 48])) commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def method_4_native_qr_model1(): """방법 4: 내장 QR Model 1 (구형)""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 4 ***\n".encode('euc-kr')) commands.append(" 내장 QR Model 1\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) qr_data = TEST_URL.encode('utf-8') data_len = len(qr_data) + 3 # Model 1 (n=49) commands.append(GS + b'(k' + bytes([3, 0, 49, 65, 49])) # Error correction L commands.append(GS + b'(k' + bytes([3, 0, 49, 69, 48])) # Size 4 commands.append(GS + b'(k' + bytes([3, 0, 49, 67, 4])) # Store data commands.append(GS + b'(k' + bytes([data_len & 0xFF, (data_len >> 8) & 0xFF, 49, 80, 48]) + qr_data) # Print commands.append(GS + b'(k' + bytes([3, 0, 49, 81, 48])) commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def method_5_raster_tiny(): """방법 5: Raster 초소형 (40x40)""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 5 ***\n".encode('euc-kr')) commands.append(" Raster 40x40 (GS v 0)\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) # 40x40 QR qr = qrcode.QRCode(version=1, box_size=1, border=1) qr.add_data(TEST_URL) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white").resize((40, 40)).convert('1') width, height = img.size pixels = img.load() width_bytes = (width + 7) // 8 commands.append(GS + b'v0' + bytes([0])) commands.append(bytes([width_bytes & 0xFF, (width_bytes >> 8) & 0xFF])) commands.append(bytes([height & 0xFF, (height >> 8) & 0xFF])) for y in range(height): for x in range(0, width, 8): byte = 0 for bit in range(8): if x + bit < width and pixels[x + bit, y] == 0: byte |= (1 << (7 - bit)) commands.append(bytes([byte])) commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def method_6_no_align(): """방법 6: 정렬 없이 + 작은 QR""" ESC = b'\x1b' GS = b'\x1d' commands = [] commands.append(ESC + b'@') # 정렬 명령 없음! commands.append("\n================================\n".encode('euc-kr')) commands.append(" *** 방법 6 ***\n".encode('euc-kr')) commands.append(" 정렬 없음 + QR 35x35\n".encode('euc-kr')) commands.append("================================\n\n".encode('euc-kr')) # 35x35 QR qr = qrcode.QRCode(version=1, box_size=1, border=1) qr.add_data(TEST_URL) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white").resize((35, 35)).convert('1') width, height = img.size pixels = img.load() # ESC * m=1 (8-dot double-density) for y in range(0, height, 8): commands.append(ESC + b'*' + bytes([1, width & 0xFF, (width >> 8) & 0xFF])) for x in range(width): byte = 0 for bit in range(min(8, height - y)): if pixels[x, y + bit] == 0: byte |= (1 << (7 - bit)) commands.append(bytes([byte])) commands.append(b'\n') commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr')) commands.append(GS + b'V' + bytes([1])) return b''.join(commands) def main(): print("="*60) print("ESC/POS QR 테스트 v2 - 더 많은 변형") print("="*60) print(f"프린터: {PRINTER_IP}:{PRINTER_PORT}") print(f"테스트 URL: {TEST_URL}") print("="*60) methods = [ ("방법 1: 30x30 ESC * m=0", method_1_tiny_qr_escstar), ("방법 2: 50x50 ESC * m=32", method_2_medium_qr_escstar_mode32), ("방법 3: 내장 QR 간단", method_3_native_qr_simple), ("방법 4: 내장 QR Model 1", method_4_native_qr_model1), ("방법 5: 40x40 Raster", method_5_raster_tiny), ("방법 6: 정렬 없음 35x35", method_6_no_align), ] results = [] for name, method_func in methods: try: data = method_func() success = send_to_printer(data, name) results.append((name, success)) except Exception as e: print(f"[{name}] ❌ 오류: {e}") results.append((name, False)) print("\n" + "="*60) print("결과 요약") print("="*60) for name, success in results: print(f"{name}: {'✅' if success else '❌'}") print("\n6장의 영수증이 나옵니다. QR이 보이는 번호를 알려주세요!") print("="*60) if __name__ == "__main__": main()