The application has been refactored. Functions have been moved to separate libraries. Many different functions have been added. Performance is still poor

This commit is contained in:
2025-02-16 21:57:01 +03:00
parent a140b7d8a0
commit cb5329ddb7
46 changed files with 5316 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from typing import Optional, Callable
import tftpy
from core.config import AppConfig
from core.exceptions import TFTPError
from core.events import event_bus, Event, EventTypes
class TFTPProtocol:
"""Протокол для работы с TFTP сервером."""
def __init__(self):
self._server: Optional[tftpy.TftpServer] = None
self._client: Optional[tftpy.TftpClient] = None
self._server_running = False
self._root_dir = AppConfig.CONFIGS_DIR
self._port = AppConfig.TFTP_PORT
self._timeout = AppConfig.TFTP_TIMEOUT
self._retries = AppConfig.TFTP_RETRIES
def configure(self, root_dir: Optional[str] = None, port: Optional[int] = None,
timeout: Optional[int] = None, retries: Optional[int] = None) -> None:
"""
Конфигурация TFTP сервера/клиента.
Args:
root_dir: Корневая директория для файлов
port: Порт TFTP сервера
timeout: Таймаут операций
retries: Количество попыток
"""
if root_dir is not None:
self._root_dir = root_dir
if port is not None:
self._port = port
if timeout is not None:
self._timeout = timeout
if retries is not None:
self._retries = retries
def start_server(self, host: str = "0.0.0.0") -> None:
"""
Запуск TFTP сервера.
Args:
host: IP-адрес для прослушивания
Raises:
TFTPError: При ошибке запуска сервера
"""
if self._server_running:
return
try:
# Создаем серверный объект
self._server = tftpy.TftpServer(self._root_dir)
# Запускаем сервер в отдельном потоке
self._server.listen(host, self._port, timeout=self._timeout)
self._server_running = True
event_bus.publish(Event(EventTypes.TFTP_SERVER_STARTED, {
"host": host,
"port": self._port,
"root_dir": self._root_dir
}))
except Exception as e:
raise TFTPError(f"Ошибка запуска TFTP сервера: {e}")
def stop_server(self) -> None:
"""Остановка TFTP сервера."""
if self._server and self._server_running:
self._server.stop()
self._server = None
self._server_running = False
event_bus.publish(Event(EventTypes.TFTP_SERVER_STOPPED, None))
def upload_file(self, filename: str, host: str, remote_filename: Optional[str] = None,
progress_callback: Optional[Callable[[int], None]] = None) -> None:
"""
Загрузка файла на удаленное устройство.
Args:
filename: Путь к локальному файлу
host: IP-адрес устройства
remote_filename: Имя файла на устройстве
progress_callback: Функция обратного вызова для отслеживания прогресса
Raises:
TFTPError: При ошибке загрузки файла
"""
if not os.path.exists(filename):
raise TFTPError(f"Файл не найден: {filename}")
try:
# Создаем клиентский объект
self._client = tftpy.TftpClient(
host,
self._port,
options={"timeout": self._timeout, "retries": self._retries}
)
# Определяем имя удаленного файла
if not remote_filename:
remote_filename = os.path.basename(filename)
event_bus.publish(Event(EventTypes.TFTP_TRANSFER_STARTED, {
"operation": "upload",
"local_file": filename,
"remote_file": remote_filename,
"host": host
}))
# Загружаем файл
self._client.upload(
remote_filename,
filename,
progress_callback
)
event_bus.publish(Event(EventTypes.TFTP_TRANSFER_COMPLETED, {
"operation": "upload",
"local_file": filename,
"remote_file": remote_filename,
"host": host
}))
except Exception as e:
event_bus.publish(Event(EventTypes.TFTP_ERROR, str(e)))
raise TFTPError(f"Ошибка загрузки файла: {e}")
def download_file(self, remote_filename: str, host: str, local_filename: Optional[str] = None,
progress_callback: Optional[Callable[[int], None]] = None) -> None:
"""
Загрузка файла с удаленного устройства.
Args:
remote_filename: Имя файла на устройстве
host: IP-адрес устройства
local_filename: Путь для сохранения файла
progress_callback: Функция обратного вызова для отслеживания прогресса
Raises:
TFTPError: При ошибке загрузки файла
"""
try:
# Создаем клиентский объект
self._client = tftpy.TftpClient(
host,
self._port,
options={"timeout": self._timeout, "retries": self._retries}
)
# Определяем имя локального файла
if not local_filename:
local_filename = os.path.join(self._root_dir, remote_filename)
event_bus.publish(Event(EventTypes.TFTP_TRANSFER_STARTED, {
"operation": "download",
"local_file": local_filename,
"remote_file": remote_filename,
"host": host
}))
# Загружаем файл
self._client.download(
remote_filename,
local_filename,
progress_callback
)
event_bus.publish(Event(EventTypes.TFTP_TRANSFER_COMPLETED, {
"operation": "download",
"local_file": local_filename,
"remote_file": remote_filename,
"host": host
}))
except Exception as e:
event_bus.publish(Event(EventTypes.TFTP_ERROR, str(e)))
raise TFTPError(f"Ошибка загрузки файла: {e}")
@property
def is_server_running(self) -> bool:
"""Проверка состояния сервера."""
return self._server_running