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


import time
import serial
import serial.tools.list_ports
import tkinter as tk
from datetime import datetime
import os
import glob

class LaserTimerFO3015:
    def __init__(self):
        self.serial_port = None
        self.port_name = None
        self.connection_type = None
        self.auto_connect()
    
    def auto_connect(self):
        """Автоматический поиск подключения к станку FO3015"""
        print("=" * 50)
        print("Поиск подключения к станку FO3015...")
        print("=" * 50)
        
        # Сначала пробуем найти COM-порты
        ports = list(serial.tools.list_ports.comports())
        
        if len(ports) > 0:
            print(f"Найдено портов: {len(ports)}")
            for port in ports:
                print(f"\nПробуем порт: {port.device}")
                print(f"Описание: {port.description}")
                
                # Пробуем разные скорости
                for baudrate in [9600, 19200, 38400, 57600, 115200]:
                    try:
                        ser = serial.Serial(
                            port=port.device,
                            baudrate=baudrate,
                            timeout=0.5,
                            bytesize=8,
                            parity='N',
                            stopbits=1
                        )
                        print(f"  Успех! Порт {port.device}, скорость {baudrate}")
                        self.serial_port = ser
                        self.port_name = port.device
                        self.connection_type = "serial"
                        return
                    except:
                        pass
        else:
            print("COM-порты не найдены")
            print("Возможно, станок подключен через Ethernet")
        
        # Если порты не найдены, пробуем найти файлы-маркеры Unicut
        self.find_unicut_files()
    
    def find_unicut_files(self):
        """Поиск файлов программы Unicut"""
        possible_paths = [
            r"C:\Program Files\Unicut",
            r"C:\Program Files (x86)\Unicut",
            r"C:\Unicut",
            r"D:\Unicut",
            r"C:\Program Files\Unimash",
            r"C:\Program Files (x86)\Unimash",
            r"C:\Unimash"
        ]
        
        print("\nПоиск файлов Unicut...")
        for path in possible_paths:
            if os.path.exists(path):
                print(f"Найдена папка: {path}")
                # Ищем лог-файлы
                log_files = glob.glob(os.path.join(path, "**", "*.log"), recursive=True)
                if log_files:
                    print(f"Найдены лог-файлы: {log_files[:5]}")
                    self.log_file = log_files[0]
                    self.connection_type = "file"
                    return
        
        print("Файлы Unicut не найдены")
    
    def check_laser_status(self):
        """Проверка статуса лазера"""
        if self.connection_type == "serial" and self.serial_port:
            return self.check_serial_status()
        elif self.connection_type == "file" and hasattr(self, 'log_file'):
            return self.check_file_status()
        return None
    
    def check_serial_status(self):
        """Проверка через COM-порт"""
        try:
            if self.serial_port.in_waiting > 0:
                data = self.serial_port.readline().decode('utf-8', errors='ignore')
                if data.strip():
                    print(f"Данные от станка: {repr(data.strip())}")
                
                data_upper = data.upper()
                
                # Команды для оптоволоконных лазеров FO3015
                laser_on_commands = [
                    'M3', 'M03',        # Стандартные команды
                    'LASER_ON',          # Лазер включен
                    'BEAM_ON',           # Луч включен
                    'POWER_ON',          # Питание включено
                    'EMISSION_ON',       # Излучение включено
                    'CUTTING_START',     # Начало резки
                    'START_CUT',         # Начало резки
                    'G1', 'G01',        # Линейное перемещение (часто с лазером)
                    'ENABLE',            # Разрешение
                ]
                
                laser_off_commands = [
                    'M5', 'M05',        # Стандартные команды
                    'LASER_OFF',         # Лазер выключен
                    'BEAM_OFF',          # Луч выключен
                    'POWER_OFF',         # Питание выключено
                    'EMISSION_OFF',      # Излучение выключено
                    'CUTTING_END',       # Конец резки
                    'STOP_CUT',          # Конец резки
                    'G0', 'G00',        # Быстрое перемещение (без лазера)
                    'DISABLE',           # Запрет
                ]
                
                for cmd in laser_on_commands:
                    if cmd in data_upper:
                        return True
                
                for cmd in laser_off_commands:
                    if cmd in data_upper:
                        return False
            return None
        except Exception as e:
            print(f"Ошибка чтения порта: {e}")
            return None
    
    def check_file_status(self):
        """Проверка через файлы Unicut"""
        try:
            if not os.path.exists(self.log_file):
                return None
            
            with open(self.log_file, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
                
                content_upper = content.upper()
                
                if 'LASER ON' in content_upper or 'CUTTING' in content_upper:
                    return True
                elif 'LASER OFF' in content_upper or 'IDLE' in content_upper:
                    return False
            return None
        except:
            return None

class TimerApp:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Секундомер FO3015")
        self.window.geometry("500x300")
        self.window.attributes('-topmost', True)
        self.window.configure(bg='#1e1e1e')
        
        self.timer = LaserTimerFO3015()
        self.total_time = 0
        self.is_cutting = False
        self.start_time = None
        self.operation_count = 0
        
        self.setup_ui()
        self.update()
    
    def setup_ui(self):
        # Заголовок
        title = tk.Label(self.window, text="ЛАЗЕРНЫЙ СТАНОК FO3015",
                        font=("Arial", 14, "bold"),
                        bg='#1e1e1e', fg='white')
        title.pack(pady=5)
        
        # Информация о подключении
        if self.timer.connection_type:
            conn_text = f"Подключение: {self.timer.connection_type.upper()}"
            conn_color = "green"
        else:
            conn_text = "Нет подключения"
            conn_color = "red"
        
        self.conn_label = tk.Label(self.window, text=conn_text,
                                   font=("Arial", 10),
                                   bg='#1e1e1e', fg=conn_color)
        self.conn_label.pack()
        
        # Таймер
        self.time_label = tk.Label(self.window, text="00:00:00",
                                   font=("Arial", 60, "bold"),
                                   bg='#1e1e1e', fg='#00ff00')
        self.time_label.pack(pady=20)
        
        # Статус
        self.status_label = tk.Label(self.window, text="ОЖИДАНИЕ",
                                     font=("Arial", 14, "bold"),
                                     bg='#1e1e1e', fg='gray')
        self.status_label.pack()
        
        # Счетчик операций
        self.count_label = tk.Label(self.window, text="Операций: 0",
                                    font=("Arial", 10),
                                    bg='#1e1e1e', fg='white')
        self.count_label.pack(pady=5)
        
        # Кнопка сброса
        reset_btn = tk.Button(self.window, text="СБРОС",
                             command=self.reset,
                             font=("Arial", 12, "bold"),
                             width=10, height=2,
                             bg='#4a4a4a', fg='white')
        reset_btn.pack(pady=10)
    
    def update(self):
        status = self.timer.check_laser_status()
        
        if status == True and not self.is_cutting:
            self.is_cutting = True
            self.start_time = time.time()
            self.operation_count += 1
            self.status_label.config(text="РЕЗКА", fg='#00ff00')
            self.count_label.config(text=f"Операций: {self.operation_count}")
            print(f"[{datetime.now().strftime('%H:%M:%S')}] РЕЗКА НАЧАЛАСЬ")
        
        elif status == False and self.is_cutting:
            cut_time = time.time() - self.start_time
            self.total_time += cut_time
            self.is_cutting = False
            self.status_label.config(text="ОЖИДАНИЕ", fg='gray')
            print(f"[{datetime.now().strftime('%H:%M:%S')}] Резка завершена: {cut_time:.2f} сек")
        
        # Обновление таймера
        if self.is_cutting:
            current = self.total_time + (time.time() - self.start_time)
        else:
            current = self.total_time
        
        hours = int(current // 3600)
        minutes = int((current % 3600) // 60)
        seconds = int(current % 60)
        self.time_label.config(text=f"{hours:02d}:{minutes:02d}:{seconds:02d}")
        
        self.window.after(100, self.update)
    
    def reset(self):
        self.total_time = 0
        self.is_cutting = False
        self.operation_count = 0
        self.time_label.config(text="00:00:00")
        self.status_label.config(text="ОЖИДАНИЕ", fg='gray')
        self.count_label.config(text="Операций: 0")
        print("Таймер сброшен")
    
    def run(self):
        self.window.mainloop()

if __name__ == "__main__":
    print("=" * 50)
    print("ПРОГРАММА ДЛЯ СТАНКА FO3015")
    print("=" * 50)
    app = TimerApp()
    app.run()