Загрузка данных
import time
import serial
import threading
import tkinter as tk
from datetime import datetime
from serial.tools import list_ports
class LaserTimer:
def __init__(self):
self.running = False
self.start_time = None
self.total_time = 0
self.last_change = None
self.serial_port = None
self.is_connected = False
# Автоматический поиск порта
self.find_port()
def find_port(self):
"""Автоматический поиск COM-порта"""
ports = list_ports.comports()
print("Найденные порты:")
for port in ports:
print(f" - {port.device}: {port.description}")
# Попробуем подключиться к первому доступному
if not self.serial_port:
try:
self.serial_port = serial.Serial(port.device, 9600, timeout=1)
self.is_connected = True
print(f"Подключено к {port.device}")
except:
print(f"Не удалось подключиться к {port.device}")
def connect_to_port(self, port_name):
"""Подключение к указанному порту"""
try:
if self.serial_port:
self.serial_port.close()
self.serial_port = serial.Serial(port_name, 9600, timeout=1)
self.is_connected = True
return True
except:
self.is_connected = False
return False
def check_laser_status(self):
"""Проверка статуса лазера через serial порт"""
try:
if self.serial_port and self.serial_port.in_waiting > 0:
data = self.serial_port.readline().decode('utf-8', errors='ignore')
print(f"Получены данные: {data.strip()}") # Для отладки
# Ищем команды включения/выключения лазера
# Разные станки могут использовать разные команды
if 'M3' in data.upper() or 'M03' in data.upper() or 'LASER_ON' in data.upper() or 'ON' in data.upper():
return True
elif 'M5' in data.upper() or 'M05' in data.upper() or 'LASER_OFF' in data.upper() or 'OFF' in data.upper():
return False
return None
except Exception as e:
print(f"Ошибка чтения порта: {e}")
return None
class TimerGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("Секундомер лазерной резки - Unimash")
self.root.geometry("500x300")
self.root.attributes('-topmost', True) # Поверх всех окон
self.root.configure(bg='#2b2b2b')
self.timer = LaserTimer()
self.total_cut_time = 0
self.is_cutting = False
self.start_cut_time = None
self.cut_count = 0
# Настройка цветов
self.bg_color = '#2b2b2b'
self.fg_color = '#ffffff'
self.accent_color = '#00ff00'
self.setup_ui()
self.monitor()
def setup_ui(self):
# Заголовок
title_label = tk.Label(self.root, text="ВРЕМЯ РЕЗКИ",
font=("Arial", 16, "bold"),
bg=self.bg_color, fg=self.fg_color)
title_label.pack(pady=10)
# Основной таймер
self.label = tk.Label(self.root, text="00:00:00",
font=("Arial", 60, "bold"),
bg=self.bg_color, fg=self.accent_color)
self.label.pack(pady=10)
# Статус
status_frame = tk.Frame(self.root, bg=self.bg_color)
status_frame.pack(pady=10)
self.status_indicator = tk.Label(status_frame, text="●",
font=("Arial", 20),
bg=self.bg_color, fg="gray")
self.status_indicator.pack(side=tk.LEFT, padx=5)
self.status_label = tk.Label(status_frame, text="Ожидание",
font=("Arial", 14),
bg=self.bg_color, fg="gray")
self.status_label.pack(side=tk.LEFT)
# Информация
self.info_label = tk.Label(self.root,
text=f"Операций: {self.cut_count} | Порт: {'Подключен' if self.timer.is_connected else 'Не подключен'}",
font=("Arial", 10),
bg=self.bg_color, fg=self.fg_color)
self.info_label.pack(pady=5)
# Кнопки
button_frame = tk.Frame(self.root, bg=self.bg_color)
button_frame.pack(pady=10)
self.reset_button = tk.Button(button_frame, text="Сбросить",
command=self.reset_timer,
width=12, font=("Arial", 11),
bg='#4a4a4a', fg='white')
self.reset_button.pack(side=tk.LEFT, padx=5)
self.export_button = tk.Button(button_frame, text="Сохранить отчет",
command=self.export_data,
width=15, font=("Arial", 11),
bg='#4a4a4a', fg='white')
self.export_button.pack(side=tk.LEFT, padx=5)
# Подсказка
hint_label = tk.Label(self.root,
text="Программа автоматически отслеживает включение лазера",
font=("Arial", 8),
bg=self.bg_color, fg='#888888')
hint_label.pack(side=tk.BOTTOM, pady=5)
def monitor(self):
"""Постоянный мониторинг состояния лазера"""
status = self.timer.check_laser_status()
# Обработка изменения статуса
if status == True and not self.is_cutting:
# Лазер начал резать
self.is_cutting = True
self.start_cut_time = time.time()
self.cut_count += 1
self.status_indicator.config(fg="green")
self.status_label.config(text="РЕЗКА", fg="green")
self.info_label.config(text=f"Операций: {self.cut_count} | Порт: {'Подключен' if self.timer.is_connected else 'Не подключен'}")
print(f"[{datetime.now().strftime('%H:%M:%S')}] Резка началась")
elif status == False and self.is_cutting:
# Лазер остановился
if self.start_cut_time:
cut_duration = time.time() - self.start_cut_time
self.total_cut_time += cut_duration
print(f"[{datetime.now().strftime('%H:%M:%S')}] Резка завершена: {cut_duration:.2f} сек")
self.is_cutting = False
self.status_indicator.config(fg="orange")
self.status_label.config(text="Ожидание", fg="orange")
# Обновление отображения времени
if self.is_cutting and self.start_cut_time:
current_time = self.total_cut_time + (time.time() - self.start_cut_time)
else:
current_time = self.total_cut_time
hours = int(current_time // 3600)
minutes = int((current_time % 3600) // 60)
seconds = int(current_time % 60)
self.label.config(text=f"{hours:02d}:{minutes:02d}:{seconds:02d}")
# Повторяем каждые 100 мс
self.root.after(100, self.monitor)
def reset_timer(self):
"""Сброс таймера"""
self.total_cut_time = 0
self.start_cut_time = None
self.is_cutting = False
self.cut_count = 0
self.label.config(text="00:00:00")
self.status_indicator.config(fg="gray")
self.status_label.config(text="Ожидание", fg="gray")
self.info_label.config(text=f"Операций: {self.cut_count} | Порт: {'Подключен' if self.timer.is_connected else 'Не подключен'}")
print("Таймер сброшен")
def export_data(self):
"""Экспорт данных в файл"""
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
filename = f"laser_time_{timestamp}.txt"
with open(filename, 'w', encoding='utf-8') as f:
f.write("="*50 + "\n")
f.write("ОТЧЕТ О РАБОТЕ ЛАЗЕРНОГО СТАНКА\n")
f.write("="*50 + "\n")
f.write(f"Дата: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Общее время резки: {self.label.cget('text')}\n")
f.write(f"Количество операций: {self.cut_count}\n")
f.write(f"Время в секундах: {self.total_cut_time:.2f}\n")
f.write("="*50 + "\n")
print(f"Отчет сохранен в файл: {filename}")
# Можно показать сообщение пользователю
tk.messagebox.showinfo("Успех", f"Отчет сохранен в файл:\n{filename}")
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = TimerGUI()
app.run()