#!/usr/bin/env python3 import tkinter as tk from tkinter import messagebox, ttk import subprocess import sys import os import re import glob from datetime import datetime import time import serial import telebot import threading import logging class MainApp: def __init__(self, root): self.root = root self.root.title("Мое Приложение") self.root.geometry("900x900") self.root.configure(bg='#f0f0f0') # Add these class variables to MainApp.__init__ after self.root.configure(bg='#f0f0f0') self.telegram_bot_token = "5481440980:AAF1oPtuwS9NCVqcNmV2G80x9r77w1NUhEg" # Replace with your bot token from BotFather self.telegram_user_id = None # Replace with the Telegram user ID to receive messages self.bot = None # Позиционируем окно по левому краю экрана self.position_window_left() # Увеличим шрифты для лучшей видимости на 7-дюймовом мониторе self.big_font = ('Arial', 24) self.medium_font = ('Arial', 20) self.small_font = ('Arial', 16) self.create_widgets() self.start_telegram_bot() # Автоматически открываем Minicom при запуске self.root.after(1000, self.open_minicom) # Задержка 1 секунда перед открытием Minicom def position_window_left(self): """Позиционирует окно по левому краю экрана""" # Получаем размеры экрана screen_width = self.root.winfo_screenwidth() screen_height = self.root.winfo_screenheight() # Получаем размеры окна window_width = 900 window_height = 900 # Вычисляем позицию для левого края x_position = 0 y_position = (screen_height - window_height) // 2 # Устанавливаем позицию окна self.root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}") def create_widgets(self): # Заголовок title_label = tk.Label( self.root, text="Главное меню", font=('Arial', 24, 'bold'), bg='#f0f0f0', fg='#333333' ) title_label.pack(pady=20) # Кнопка Авто STM32 self.auto_stm32_btn = tk.Button( self.root, text="Тестовое ПО", font=self.big_font, bg='#4CAF50', fg='white', width=15, height=2, command=lambda: self.auto_mode('test') ) self.auto_stm32_btn.pack(pady=10) # Кнопка Авто ESP32 self.auto_esp32_btn = tk.Button( self.root, text="Рабочее ПО", font=self.big_font, bg='#2196F3', fg='white', width=15, height=2, command=lambda: self.auto_mode('work') ) self.auto_esp32_btn.pack(pady=10) # Кнопка Minicom self.minicom_btn = tk.Button( self.root, text="Получить пароль", font=self.big_font, bg='#FF9800', fg='white', width=15, height=2, command=self.get_password ) self.minicom_btn.pack(pady=10) # Кнопка Выход self.exit_btn = tk.Button( self.root, text="Выход", font=self.big_font, bg='#f44336', fg='white', width=15, height=2, command=self.exit_app ) self.exit_btn.pack(pady=10) # Область для лога log_frame = tk.Frame(self.root, bg='#f0f0f0') log_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) tk.Label( log_frame, text="Лог выполнения:", font=self.medium_font, bg='#f0f0f0', fg='#333333' ).pack(anchor=tk.W) # Текстовое поле для лога с прокруткой log_container = tk.Frame(log_frame) log_container.pack(fill=tk.BOTH, expand=True, pady=5) self.log_text = tk.Text( log_container, height=12, font=self.small_font, bg='#2c3e50', fg='#ecf0f1', insertbackground='white', wrap=tk.WORD ) scrollbar = tk.Scrollbar(log_container, orient=tk.VERTICAL, command=self.log_text.yview) self.log_text.configure(yscrollcommand=scrollbar.set) self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # Статус бар self.status_var = tk.StringVar() self.status_var.set("Готов к работе") status_bar = tk.Label( self.root, textvariable=self.status_var, font=self.medium_font, bg='#dddddd', relief=tk.SUNKEN, anchor=tk.W ) status_bar.pack(side=tk.BOTTOM, fill=tk.X) # Добавляем начальное сообщение в лог self.add_to_log("✅ Приложение запущено и готово к работе") self.add_to_log("📐 Окно позиционировано по левому краю (900x900)") def start_telegram_bot(self): """Запускает Telegram бота в фоновом потоке""" try: self.bot = telebot.TeleBot(self.telegram_bot_token) # Обработчик команды /edison @self.bot.message_handler(commands=['edison']) def handle_edison(message): self.telegram_chat_id = message.chat.id response = ( f"🔧 Режим Edison активирован!\n" f"📋 Ваш ID: {message.chat.id}\n" f"✅ Теперь я буду присылать сюда все пароли" ) self.bot.send_message(message.chat.id, response) print(f"✅ Chat ID сохранен: {message.chat.id}") self.add_to_log(f"✅ Telegram: получен chat_id {message.chat.id}") # Запускаем бота в отдельном потоке bot_thread = threading.Thread(target=self.bot.polling, daemon=True) bot_thread.start() print("✅ Telegram бот запущен. Ожидаю команду /edison") self.add_to_log("✅ Telegram бот запущен. Отправьте /edison в бот") except Exception as e: print(f"❌ Ошибка запуска бота: {e}") self.add_to_log(f"❌ Ошибка запуска Telegram бота: {e}") def send_telegram_message(self, message): """Отправляет сообщение в Telegram""" try: if self.bot and self.telegram_chat_id: self.bot.send_message(self.telegram_chat_id, message) print(f"✅ Сообщение отправлено: {message}") return True else: if not self.telegram_chat_id: print("⚠️ Chat ID не установлен. Отправьте /edison боту") self.add_to_log("⚠️ Telegram: chat_id не установлен. Отправьте /edison") return False except Exception as e: print(f"❌ Ошибка отправки: {e}") self.add_to_log(f"❌ Ошибка отправки в Telegram: {e}") return False def get_password(self): """Получает пароль от устройства""" self.add_to_log("🔑 Запуск процесса получения пароля...") self.status_var.set("Получение пароля...") try: # Прошивка STM32 с firmware для получения UID self.add_to_log("🔍 Прошивка STM32 для получения UID...") stm32_firmware = os.path.expanduser("~/fw/getuid/STM32_GET_UID.bin") if os.path.exists(stm32_firmware): # Стираем флеш-память STM32 self.add_to_log("🧹 Стирание флеш-памяти STM32...") erase_result = subprocess.run([ 'st-flash', 'erase' ], capture_output=True, text=True, timeout=30) if erase_result.returncode != 0: self.add_to_log(f"❌ Ошибка стирания STM32: {erase_result.stderr}") return False # Прошивка STM32 # Прошивка ESP32 self.add_to_log("📥 Прошивка ESP32 для получения пароля...") port = "/dev/ttyUSB0" # Файлы для ESP32 bootloader_path = os.path.expanduser("~/fw/getuid/bootloader.bin") firmware_path = os.path.expanduser("~/fw/getuid/ET_22KW_1.0b.bin") partition_path = os.path.expanduser("~/fw/getuid/partition-table.bin") www_path = os.path.expanduser("~/fw/getuid/www.bin") if not all([os.path.exists(p) for p in [bootloader_path, firmware_path, partition_path, www_path]]): self.add_to_log("❌ Не все файлы прошивки GetUID найдены") return False # Стираем флеш-память ESP32 self.add_to_log("🧹 Стирание флеш-памяти ESP32...") esp_erase_result = subprocess.run([ 'esptool.py', '--chip', 'esp32', '--port', port, 'erase_flash' ], capture_output=True, text=True, timeout=60) time.sleep(60) # Ждем после стирания # Прошиваем ESP32 flash_command = [ 'esptool.py', '--chip', 'esp32', '--port', port, '--baud', '460800', 'write_flash', '--flash_mode', 'dio', '--flash_freq', '40m', '--flash_size', 'detect', '0x1000', bootloader_path, '0x10000', firmware_path, '0x8000', partition_path, '0x210000', www_path ] self.add_to_log(f"🔧 Команда прошивки: {' '.join(flash_command)}") flash_result = subprocess.run(flash_command, capture_output=True, text=True, timeout=180) if flash_result.returncode != 0: self.add_to_log(f"❌ Ошибка прошивки ESP32: {flash_result.stderr}") return False self.add_to_log("📥 Прошивка STM32 специальной прошивкой...") flash_result = subprocess.run([ 'st-flash', '--reset', 'write', stm32_firmware, '0x08000000' ], capture_output=True, text=True, timeout=30) if flash_result.returncode != 0: self.add_to_log(f"❌ Ошибка прошивки STM32: {flash_result.stderr}") return False # Перезагрузка устройств self.add_to_log("🔄 Перезагрузка устройств...") # Перезагрузка ESP32 subprocess.run(['esptool.py', '--port', port, 'run'], capture_output=True, text=True, timeout=20) time.sleep(5) # Перезагрузка STM32 subprocess.run(['st-flash', 'reset'], capture_output=True, text=True, timeout=20) time.sleep(5) # Повторяем перезагрузку для надежности self.add_to_log("🔄 Повторная перезагрузка устройств...") subprocess.run(['esptool.py', '--port', port, 'run'], capture_output=True, text=True, timeout=20) time.sleep(5) subprocess.run(['st-flash', 'reset'], capture_output=True, text=True, timeout=20) # Чтение данных с COM-порта self.add_to_log("📋 Чтение данных с порта...") try: with serial.Serial(port, 115200, timeout=20) as ser: time.sleep(2) data = ser.read(10000) received_data = data.decode(errors='ignore') # self.add_to_log(f"📟 Полученные данные: {received_data}") # Updated pattern to match "Hash:: XXXXXXXXXXXX" format import re password_match = re.search(r'Hash:: ([A-Za-z0-9]+)', received_data) if password_match: password = password_match.group(1) self.add_to_log(f"🔑 Найден пароль: {password}") self.status_var.set(f"Пароль: {password}") success = self.send_telegram_message(f"🔐 Новый пароль получен: {password}") if success: self.add_to_log("✅ Пароль отправлен в Telegram") else: self.add_to_log("❌ Не удалось отправить пароль в Telegram") return password else: self.add_to_log("❌ Пароль не найден в полученных данных") return None except serial.SerialException as e: self.add_to_log(f"❌ Ошибка чтения COM-порта: {str(e)}") return None else: self.add_to_log(f"❌ Файл прошивки STM32 для получения UID не найден: {stm32_firmware}") return None except Exception as e: self.add_to_log(f"❌ Произошла ошибка при получении пароля: {str(e)}") self.status_var.set("Ошибка получения пароля") return None def open_minicom(self): """Открывает minicom в отдельном терминале""" try: self.status_var.set("Запуск minicom...") self.add_to_log("🔄 Запускаю minicom...") # Автоматически находим порт ports = glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') if ports: port = "/dev/ttyUSB1" self.add_to_log(f"🔌 Найден порт: {port}") subprocess.Popen([ 'lxterminal', '--geometry=80x60', '-e', f'bash -c "minicom -D {port} -b 115200; exec bash"' ]) self.status_var.set("Minicom запущен") self.add_to_log(f"✅ Minicom запущен на {port}") else: self.add_to_log("❌ COM-порты не найдены") except Exception as e: self.status_var.set("Ошибка запуска minicom") self.add_to_log(f"❌ Ошибка запуска minicom: {str(e)}") def add_to_log(self, message): """Добавляет сообщение в лог с временной меткой""" timestamp = datetime.now().strftime("%H:%M:%S") formatted_message = f"[{timestamp}] {message}\n" self.log_text.insert(tk.END, formatted_message) self.log_text.see(tk.END) self.root.update_idletasks() def find_serial_ports(self): """Поиск доступных COM-портов""" ports = [] # Поиск на Linux if sys.platform.startswith('linux'): ports = glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') # Поиск на Windows elif sys.platform.startswith('win'): ports = [f"COM{i}" for i in range(1, 256)] # Поиск на MacOS elif sys.platform.startswith('darwin'): ports = glob.glob('/dev/tty.*') available_ports = [] for port in ports: if sys.platform.startswith('win'): # На Windows просто проверяем существование if os.path.exists(port): available_ports.append(port) else: # На Linux/Mac проверяем доступность try: if os.path.exists(port) and os.access(port, os.R_OK): available_ports.append(port) except: pass return available_ports def check_stm32_connection(self): """Проверка подключения STM32""" try: result = subprocess.run(['st-info', '--chipid'], capture_output=True, text=True, timeout=10) chip_id = None # Ищем hex число в выводе match = re.search(r'0x[0-9A-Fa-f]+', result.stdout + result.stderr) if match: chip_id = match.group(0) if chip_id and chip_id != "0x0000": return True, chip_id else: return False, None except Exception as e: return False, None def check_esp32_connection(self): """Проверка подключения ESP32""" try: # Ищем порт ESP32 ports = self.find_serial_ports() if not ports: return False, None, None port = "/dev/ttyUSB0" # Берем первый доступный порт # Пробуем получить информацию о чипе ESP32 result = subprocess.run([ 'esptool.py', '--port', port, 'chip_id' ], capture_output=True, text=True, timeout=10) if result.returncode == 0: return True, port, "ESP32 обнаружен" else: return False, port, None except Exception as e: return False, None, str(e) def auto_mode(self, mcu_type): """Автоматический режим для STM32 или ESP32""" self.status_var.set(f"Режим Авто {mcu_type.upper()} активирован") self.add_to_log(f"🔄 Запуск автоматического режима для {mcu_type.upper()}...") if mcu_type == 'test': self.auto_mode_erase_stm32() time.sleep(3) self.auto_mode_test_esp32() time.sleep(3) self.auto_mode_test_stm32() elif mcu_type == 'work': self.auto_mode_work() def auto_mode_erase_stm32(self): """Тестовое ПО""" flash_success = False try: # Проверка подключения микроконтроллера self.add_to_log("🔍 Проверка подключения STM32...") connected, chip_id = self.check_stm32_connection() if connected: self.status_var.set(f"✅ STM32 подключен, Chip ID: {chip_id}") self.add_to_log(f"✅ STM32 подключен, Chip ID: {chip_id}") # Проверка файла прошивки self.add_to_log("🔍 Очистка памяти STM32...") flash_result = subprocess.run([ 'st-flash', 'erase' ], capture_output=True, text=True, timeout=60) if flash_result.returncode == 0: self.status_var.set("✅ Очистка STM32 завершена успешно!") self.add_to_log("✅ Очистка STM32 завершена успешно!") flash_success = True else: self.status_var.set("❌ Ошибка очистки STM32") self.add_to_log(f"❌ Ошибка очистки STM32: {flash_result.stderr}") else: self.status_var.set("❌ STM32 не подключен") self.add_to_log("❌ STM32 не подключен") except subprocess.TimeoutExpired: self.status_var.set("❌ Таймаут операции STM32") self.add_to_log("❌ Таймаут операции STM32!") except Exception as e: self.status_var.set("❌ Ошибка выполнения STM32") self.add_to_log(f"❌ Произошла ошибка STM32: {str(e)}") self.add_to_log("🔚 Очистка STM32 завершена") def auto_mode_test_stm32(self): """Тестовое ПО""" flash_success = False try: # Проверка подключения микроконтроллера self.add_to_log("🔍 Проверка подключения STM32...") connected, chip_id = self.check_stm32_connection() if connected: self.status_var.set(f"✅ STM32 подключен, Chip ID: {chip_id}") self.add_to_log(f"✅ STM32 подключен, Chip ID: {chip_id}") # Проверка файла прошивки self.add_to_log("🔍 Поиск файла прошивки STM32...") firmware_path = os.path.expanduser("~/fw/TestStand_FW_STM32.bin") if os.path.exists(firmware_path): file_size = os.path.getsize(firmware_path) self.status_var.set("✅ Файл прошивки STM32 найден") self.add_to_log(f"✅ Файл прошивки найден: TestStand_FW_STM32.bin ({file_size} байт)") # Прошивка микроконтроллера self.status_var.set("🔄 Идет прошивка STM32...") self.add_to_log("🔄 Начинаю прошивку STM32...") flash_result = subprocess.run([ 'st-flash', '--reset', 'write', firmware_path, '0x08000000' ], capture_output=True, text=True, timeout=60) if flash_result.returncode == 0: self.status_var.set("✅ Прошивка STM32 завершена успешно!") self.add_to_log("✅ Прошивка STM32 завершена успешно!") flash_success = True else: self.status_var.set("❌ Ошибка прошивки STM32") self.add_to_log(f"❌ Ошибка прошивки STM32: {flash_result.stderr}") else: self.status_var.set("❌ Файл прошивки STM32 не найден") self.add_to_log("❌ Файл прошивки STM32 не найден") self.show_available_files() else: self.status_var.set("❌ STM32 не подключен") self.add_to_log("❌ STM32 не подключен") except subprocess.TimeoutExpired: self.status_var.set("❌ Таймаут операции STM32") self.add_to_log("❌ Таймаут операции STM32!") except Exception as e: self.status_var.set("❌ Ошибка выполнения STM32") self.add_to_log(f"❌ Произошла ошибка STM32: {str(e)}") self.add_to_log("🔚 Автоматический режим STM32 завершен") def auto_mode_test_esp32(self): try: # Проверка подключения микроконтроллера self.add_to_log("🔍 Проверка подключения ESP32...") connected, port, chip_info = self.check_esp32_connection() port = "/dev/ttyUSB0" if connected and port: self.status_var.set(f"✅ ESP32 подключен на {port}") self.add_to_log(f"✅ ESP32 подключен на {port}") if chip_info: self.add_to_log(f"ℹ️ {chip_info}") # Проверка файлов прошивки ESP32 self.add_to_log("🔍 Поиск файлов прошивки ESP32...") bootloader_path = os.path.expanduser("~/fw/bootloader.bin") firmware_path = os.path.expanduser("~/fw/TestStand_FW_ESP32.bin") partition_path = os.path.expanduser("~/fw/partition-table.bin") files_exist = all([ os.path.exists(bootloader_path), os.path.exists(firmware_path), os.path.exists(partition_path) ]) if files_exist: self.status_var.set("✅ Файлы прошивки ESP32 найдены") self.add_to_log("✅ Все файлы прошивки ESP32 найдены:") self.add_to_log(f" - bootloader.bin ({os.path.getsize(bootloader_path)} байт)") self.add_to_log(f" - TestStand_FW_ESP32.bin ({os.path.getsize(firmware_path)} байт)") self.add_to_log(f" - partition-table.bin ({os.path.getsize(partition_path)} байт)") # Прошивка ESP32 self.status_var.set("🔄 Идет прошивка ESP32...") self.add_to_log("🔄 Начинаю прошивку ESP32...") flash_command = [ 'esptool.py', '--chip', 'esp32', '--port', port, '--baud', '576000', 'write_flash', '--flash_mode', 'dio', '--flash_freq', '40m', '--flash_size', 'detect', '0x1000', bootloader_path, '0x10000', firmware_path, '0x8000', partition_path ] self.add_to_log(f"🔧 Команда прошивки: {' '.join(flash_command)}") flash_result = subprocess.run(flash_command, capture_output=True, text=True, timeout=120) if flash_result.returncode == 0: self.status_var.set("✅ Прошивка ESP32 завершена успешно!") self.add_to_log("✅ Прошивка ESP32 завершена успешно!") flash_success = True else: self.status_var.set("❌ Ошибка прошивки ESP32") self.add_to_log(f"❌ Ошибка прошивки ESP32: {flash_result.stderr}") else: self.status_var.set("❌ Не все файлы прошивки ESP32 найдены") self.add_to_log("❌ Не все файлы прошивки ESP32 найдены") self.show_available_files() else: self.status_var.set("❌ ESP32 не подключен") self.add_to_log("❌ ESP32 не подключен или порт не найден") except subprocess.TimeoutExpired: self.status_var.set("❌ Таймаут операции ESP32") self.add_to_log("❌ Таймаут операции ESP32!") except Exception as e: self.status_var.set("❌ Ошибка выполнения ESP32") self.add_to_log(f"❌ Произошла ошибка ESP32: {str(e)}") self.add_to_log("🔚 Автоматический режим ESP32 завершен") def auto_mode_work(self): """Рабочее ПО""" flash_success = False try: # Проверка подключения микроконтроллера self.add_to_log("🔍 Проверка подключения STM32...") connected, chip_id = self.check_stm32_connection() if connected: self.status_var.set(f"✅ STM32 подключен, Chip ID: {chip_id}") self.add_to_log(f"✅ STM32 подключен, Chip ID: {chip_id}") # Проверка файла прошивки self.add_to_log("🔍 Поиск файла прошивки STM32...") firmware_path = os.path.expanduser("~/fw/w/STM_2.08_NO_PROTECTION.bin") if os.path.exists(firmware_path): file_size = os.path.getsize(firmware_path) self.status_var.set("✅ Файл прошивки STM32 найден") self.add_to_log(f"✅ Файл прошивки найден: TestStand_FW_STM32.bin ({file_size} байт)") # Прошивка микроконтроллера self.status_var.set("🔄 Идет прошивка STM32...") self.add_to_log("🔄 Начинаю прошивку STM32...") flash_result = subprocess.run([ 'st-flash', '--reset', 'write', firmware_path, '0x08000000' ], capture_output=True, text=True, timeout=30) if flash_result.returncode == 0: self.status_var.set("✅ Прошивка STM32 завершена успешно!") self.add_to_log("✅ Прошивка STM32 завершена успешно!") flash_success = True else: self.status_var.set("❌ Ошибка прошивки STM32") self.add_to_log(f"❌ Ошибка прошивки STM32: {flash_result.stderr}") else: self.status_var.set("❌ Файл прошивки STM32 не найден") self.add_to_log("❌ Файл прошивки STM32 не найден") self.show_available_files() else: self.status_var.set("❌ STM32 не подключен") self.add_to_log("❌ STM32 не подключен") except subprocess.TimeoutExpired: self.status_var.set("❌ Таймаут операции STM32") self.add_to_log("❌ Таймаут операции STM32!") except Exception as e: self.status_var.set("❌ Ошибка выполнения STM32") self.add_to_log(f"❌ Произошла ошибка STM32: {str(e)}") self.add_to_log("🔚 Автоматический режим STM32 завершен") """Автоматический режим для ESP32""" flash_success = False try: # Проверка подключения микроконтроллера self.add_to_log("🔍 Проверка подключения ESP32...") connected, port, chip_info = self.check_esp32_connection() if connected and port: self.status_var.set(f"✅ ESP32 подключен на {port}") self.add_to_log(f"✅ ESP32 подключен на {port}") if chip_info: self.add_to_log(f"ℹ️ {chip_info}") # Проверка файлов прошивки ESP32 self.add_to_log("🔍 Поиск файлов прошивки ESP32...") bootloader_path = os.path.expanduser("~/fw/w/bootloader.bin") firmware_path = os.path.expanduser("~/fw/w/ET_22KW_1.0b.bin") partition_path = os.path.expanduser("~/fw/w/partition-table.bin") www_path = os.path.expanduser("~/fw/w/www.bin") files_exist = all([ os.path.exists(bootloader_path), os.path.exists(firmware_path), os.path.exists(partition_path), os.path.exists(www_path) ]) if files_exist: self.status_var.set("✅ Файлы прошивки ESP32 найдены") self.add_to_log("✅ Все файлы прошивки ESP32 найдены:") self.add_to_log(f" - bootloader.bin ({os.path.getsize(bootloader_path)} байт)") self.add_to_log(f" - TestStand_FW_ESP32.bin ({os.path.getsize(firmware_path)} байт)") self.add_to_log(f" - partition-table.bin ({os.path.getsize(partition_path)} байт)") self.add_to_log(f" - www.bin ({os.path.getsize(www_path)} байт)") # Прошивка ESP32 self.status_var.set("🔄 Идет прошивка ESP32...") self.add_to_log("🔄 Начинаю прошивку ESP32...") flash_command = [ 'esptool.py', '--chip', 'esp32', '--port', port, '--baud', '576000', 'write_flash', '--flash_mode', 'dio', '--flash_freq', '40m', '--flash_size', 'detect', '0x1000', bootloader_path, '0x10000', firmware_path, '0x8000', partition_path, '0x210000', www_path ] self.add_to_log(f"🔧 Команда прошивки: {' '.join(flash_command)}") flash_result = subprocess.run(flash_command, capture_output=True, text=True, timeout=120) if flash_result.returncode == 0: self.status_var.set("✅ Прошивка ESP32 завершена успешно!") self.add_to_log("✅ Прошивка ESP32 завершена успешно!") flash_success = True else: self.status_var.set("❌ Ошибка прошивки ESP32") self.add_to_log(f"❌ Ошибка прошивки ESP32: {flash_result.stderr}") else: self.status_var.set("❌ Не все файлы прошивки ESP32 найдены") self.add_to_log("❌ Не все файлы прошивки ESP32 найдены") self.show_available_files() else: self.status_var.set("❌ ESP32 не подключен") self.add_to_log("❌ ESP32 не подключен или порт не найден") except subprocess.TimeoutExpired: self.status_var.set("❌ Таймаут операции ESP32") self.add_to_log("❌ Таймаут операции ESP32!") except Exception as e: self.status_var.set("❌ Ошибка выполнения ESP32") self.add_to_log(f"❌ Произошла ошибка ESP32: {str(e)}") self.add_to_log("🔚 Автоматический режим ESP32 завершен") def show_available_files(self): """Показывает доступные файлы в папке fw""" fw_dir = os.path.expanduser("~/fw") if os.path.exists(fw_dir): files = os.listdir(fw_dir) bin_files = [f for f in files if f.endswith('.bin')] if bin_files: self.add_to_log("📁 Доступные файлы в папке fw:") for file in bin_files: self.add_to_log(f" - {file}") else: self.add_to_log("📁 В папке fw нет .bin файлов") else: self.add_to_log("📁 Папка fw не существует") def exit_app(self): if messagebox.askyesno("Выход", "Вы уверены, что хотите выйти?"): self.status_var.set("Завершение работы...") self.add_to_log("🔴 Приложение завершает работу...") self.root.quit() sys.exit() def main(): try: root = tk.Tk() app = MainApp(root) root.mainloop() except KeyboardInterrupt: print("\nПриложение завершено") except Exception as e: print(f"Ошибка: {e}") messagebox.showerror("Ошибка", f"Произошла ошибка: {e}") if __name__ == "__main__": main()