Загрузка данных


#!/usr/bin/env python3
"""
Супер-сканер для любого USB-принтера на Mac
Пробует все порты, все скорости, все команды
"""

import serial
import serial.tools.list_ports
import time
import sys
import os
import glob
from typing import Optional, List

# Все возможные скорости
BAUDRATES = [9600, 19200, 38400, 57600, 115200, 230400, 4800, 2400, 1200]

# Все возможные варианты портов на Mac
PORT_PATTERNS = [
    "/dev/cu.usbmodem*",
    "/dev/cu.usbserial*",
    "/dev/cu.wchusbserial*",
    "/dev/cu.SLAB_USBtoUART*",
    "/dev/tty.usbmodem*",
    "/dev/tty.usbserial*",
    "/dev/tty.wchusbserial*",
    "/dev/cu.*",
    "/dev/tty.*",
]

# Команды для теста (разные протоколы)
COMMAND_SETS = [
    # Простой текст
    [b"Test\n\n"],
    
    # ESC/POS
    [b"\x1b\x40", b"ESC/POS\n\n"],
    
    # ESC/POS с жирным
    [b"\x1b\x40", b"\x1b\x45\x01", b"BOLD", b"\x1b\x45\x00", b"\n\n"],
    
    # ESC/POS с выравниванием
    [b"\x1b\x40", b"\x1b\x61\x01", b"CENTER\n", b"\x1b\x61\x00", b"\n"],
    
    # Jieli native
    [b"\x1b\x40", b"\x1d\x61\x01", b"Jieli\n\n"],
    
    # Просто символы
    [b"Hello World!\n\n\n"],
    
    # С обрезкой
    [b"\x1b\x40", b"Test\n", b"\x1d\x56\x00"],
    
    # С инициализацией
    [b"\x1b\x40", b"\x1b\x33\x18", b"Init test\n\n"],
]

def get_all_ports() -> List[str]:
    """Возвращает все возможные порты"""
    ports = []
    
    # 1. Через pyserial
    for port in serial.tools.list_ports.comports():
        ports.append(port.device)
        if hasattr(port, 'name') and port.name:
            ports.append(f"/dev/cu.{port.name}")
            ports.append(f"/dev/tty.{port.name}")
    
    # 2. Через glob паттерны
    for pattern in PORT_PATTERNS:
        for port in glob.glob(pattern):
            if port not in ports:
                ports.append(port)
    
    # 3. Самые популярные имена
    common_names = [
        "/dev/cu.usbmodem",
        "/dev/cu.usbserial",
        "/dev/cu.wchusbserial",
        "/dev/tty.usbmodem",
        "/dev/tty.usbserial",
    ]
    for base in common_names:
        for i in range(10):
            port = f"{base}{i}"
            if os.path.exists(port) and port not in ports:
                ports.append(port)
    
    # 4. Ищем любые tty/cu порты
    for port in glob.glob("/dev/cu.*"):
        if port not in ports:
            ports.append(port)
    for port in glob.glob("/dev/tty.*"):
        if port not in ports:
            ports.append(port)
    
    # Фильтруем системные порты
    blacklist = ["cu.bluetooth", "cu.Bluetooth", "cu.wlan", "cu.debug", "tty.Bluetooth"]
    ports = [p for p in ports if not any(x in p.lower() for x in blacklist)]
    
    return list(dict.fromkeys(ports))  # Убираем дубликаты

def test_port(port: str, baud: int) -> bool:
    """Пробует открыть порт и отправить тестовые команды"""
    try:
        ser = serial.Serial(
            port,
            baudrate=baud,
            bytesize=8,
            parity='N',
            stopbits=1,
            timeout=1,
            write_timeout=1
        )
        
        if not ser.is_open:
            return False
        
        # Пробуем все команды
        for cmd_set in COMMAND_SETS:
            try:
                ser.reset_input_buffer()
                ser.reset_output_buffer()
                
                for cmd in cmd_set:
                    ser.write(cmd)
                    time.sleep(0.05)
                
                # Проверяем, есть ли ответ
                response = ser.read(10)
                if response:
                    return True
                    
            except:
                continue
        
        ser.close()
        return False
        
    except:
        return False

def find_printer() -> Optional[tuple]:
    """Агрессивный поиск принтера"""
    ports = get_all_ports()
    
    print(f"[*] Найдено {len(ports)} портов для проверки")
    
    # Показываем порты
    for i, port in enumerate(ports[:10]):
        print(f"   {i+1}. {port}")
    if len(ports) > 10:
        print(f"   ... и еще {len(ports)-10} портов")
    
    print("\n[*] Начинаю сканирование...")
    print("    (может занять несколько минут)\n")
    
    tested = 0
    for port in ports:
        # Проверяем, существует ли порт
        if not os.path.exists(port):
            continue
            
        for baud in BAUDRATES:
            tested += 1
            if tested % 20 == 0:
                print(f"[*] Проверено {tested} комбинаций...")
            
            try:
                if test_port(port, baud):
                    print(f"\n[+] НАЙДЕНО! Порт: {port}, Скорость: {baud}")
                    return (port, baud)
            except:
                continue
    
    print(f"\n[*] Всего проверено {tested} комбинаций")
    return None

def interactive_test(port: str, baud: int):
    """Интерактивный тест найденного принтера"""
    print("\n" + "="*60)
    print(f"[✓] Принтер найден на {port} ({baud} бод)")
    print("="*60)
    print("\nПробую разные команды печати...")
    
    try:
        ser = serial.Serial(port, baudrate=baud, timeout=2, write_timeout=2)
        
        # Пробуем все наборы команд по очереди
        for i, cmd_set in enumerate(COMMAND_SETS):
            try:
                print(f"\n[*] Команда #{i+1}...", end=" ", flush=True)
                ser.reset_input_buffer()
                ser.reset_output_buffer()
                
                for cmd in cmd_set:
                    ser.write(cmd)
                    time.sleep(0.1)
                
                print("ОТПРАВЛЕНО")
                print("   (если что-то напечаталось - нажмите Ctrl+C)")
                time.sleep(2)
                
            except Exception as e:
                print(f"ошибка: {e}")
        
        print("\n" + "="*60)
        print("Если ничего не напечаталось, попробуй:")
        print("1. Перезагрузи принтер")
        print("2. Подключи через другой USB-порт")
        print("3. Нажми на принтере кнопку питания дважды")
        print("4. Напиши мне модель принтера")
        print("="*60)
        
        ser.close()
        
    except Exception as e:
        print(f"[!] Ошибка: {e}")

def main():
    print("="*70)
    print("СУПЕР-СКАНЕР ДЛЯ USB-ПРИНТЕРОВ НА MAC")
    print("="*70)
    
    # Проверяем доступ к портам
    try:
        import serial
    except ImportError:
        print("[!] Установи pyserial: pip install pyserial")
        sys.exit(1)
    
    # Ищем принтер
    result = find_printer()
    
    if result:
        port, baud = result
        interactive_test(port, baud)
    else:
        print("\n[!] Принтер не найден!")
        print("\nПроверь:")
        print("  1. Подключен ли USB-кабель")
        print("  2. Нажат ли 'Разрешить' в диалоге macOS")
        print("  3. Включен ли принтер (горит индикатор)")
        print("  4. Попробуй другой USB-порт на Mac")
        print("  5. Перезагрузи принтер (выключи/включи)")
        print("\nЕсли принтер работает на другом компьютере,")
        print("напиши его модель - поищу драйвер специально.")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n[!] Остановлено пользователем")
        sys.exit(0)