Explorar el Código

Merge branch 'master' of u23-27burdyko/up into master

ypv hace 1 semana
padre
commit
c62f8c76c6
Se han modificado 1 ficheros con 372 adiciones y 0 borrados
  1. 372 0
      ОАиП/2025-26/36гр/1 сем/Бурдыко/network_info.py

+ 372 - 0
ОАиП/2025-26/36гр/1 сем/Бурдыко/network_info.py

@@ -0,0 +1,372 @@
+import tkinter as tk
+from tkinter import messagebox, ttk
+import sqlite3
+import socket
+import requests
+import uuid
+import psutil 
+import netifaces 
+from pythonping import ping as python_ping
+import time
+import os
+
+# *** Утилитарные функции ***
+
+def get_size(bytes_count):
+    """
+    Преобразует байты в удобочитаемый формат (B, KB, MB, GB, TB).
+    """
+    if not isinstance(bytes_count, (int, float)) or bytes_count is None:
+        return "N/A"
+        
+    for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:
+        if bytes_count < 1024.0:
+            return f"{bytes_count:.2f} {unit}"
+        bytes_count /= 1024.0
+    return f"{bytes_count:.2f} PB"
+
+def format_report(data, target_host):
+    """
+    Форматирует все собранные данные в одну строку для вывода в файл и консоль.
+    """
+    # Добавляем метку времени начала отчета
+    timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
+    
+    report_lines = []
+    report_lines.append("="*50)
+    report_lines.append("           СВОДНАЯ ИНФОРМАЦИЯ О СЕТИ")
+    report_lines.append("="*50)
+    report_lines.append(f"Дата и время отчета: {timestamp}")
+    report_lines.append("-" * 30)
+    
+    # Блок 1: Системная информация
+    report_lines.append("🖥️  Система:")
+    report_lines.append(f"  Имя компьютера: {data.get('hostname', 'N/A')}")
+    report_lines.append(f"  Сетевой адаптер: {data.get('interface_name', 'N/A')}")
+    report_lines.append(f"  MAC-адрес: {data.get('mac_address', 'N/A')}")
+    report_lines.append("-" * 30)
+    
+    # Блок 2: IP-адреса и шлюз
+    report_lines.append(f"🌐 IP-адреса:")
+    report_lines.append(f"  Внутренний IP: {data.get('local_ip', 'N/A')}")
+    report_lines.append(f"  IP шлюза (роутера): {data.get('gateway_ip', 'N/A')}")
+    report_lines.append(f"  Внешний IP: {data.get('external_ip', 'N/A')}")
+    report_lines.append("-" * 30)
+
+    # Блок 3: Объем данных
+    report_lines.append(f"📊 Общий объем данных (с момента загрузки ОС):")
+    report_lines.append(f"  Отправлено: {get_size(data.get('total_sent'))}")
+    report_lines.append(f"  Получено: {get_size(data.get('total_recv'))}")
+    report_lines.append("-" * 30)
+    
+    # Блок 4: Пинг
+    report_lines.append(f"⏱️  Пинг и потеря пакетов:")
+    
+    # Пинг до шлюза
+    report_lines.append(f"  - До шлюза ({data.get('gateway_ip', 'N/A')}):")
+    ping_gw = data.get('ping_gateway_ms')
+    loss_gw = data.get('loss_gateway_percent')
+    if ping_gw is not None:
+        report_lines.append(f"    Средний пинг: {ping_gw:.2f} мс")
+        report_lines.append(f"    Потеря пакетов: {loss_gw:.2f}%")
+    else:
+        report_lines.append("    Не удалось проверить.")
+        
+    # Пинг до ya.ru
+    report_lines.append(f"  - До {target_host}:")
+    ping_ext = data.get('ping_ya_ru_ms')
+    loss_ext = data.get('loss_ya_ru_percent')
+    if ping_ext is not None:
+        report_lines.append(f"    Средний пинг: {ping_ext:.2f} мс")
+        report_lines.append(f"    Потеря пакетов: {loss_ext:.2f}%")
+    else:
+        report_lines.append("    Не удалось проверить (проверьте подключение к Интернету).")
+    report_lines.append("-" * 30)
+    
+    # Блок 5: Скорость
+    report_lines.append(f"📶 Скорость Интернета (Yandex Internet Speed Test):")
+    dl_speed = data.get('download_speed_mbps')
+    ul_speed = data.get('upload_speed_mbps')
+    
+    if dl_speed is not None:
+        report_lines.append(f"  Скорость загрузки: {dl_speed:.2f} Мбит/с")
+        report_lines.append(f"  Скорость выгрузки: {ul_speed:.2f} Мбит/с")
+    else:
+        report_lines.append("  Тестирование скорости не было выполнено или завершилось ошибкой.")
+
+    report_lines.append("="*50)
+    
+    return "\n".join(report_lines)
+
+# *** Функции для измерений ***
+
+def get_network_io_total():
+    """Получает общий объем отправленных и полученных данных."""
+    try:
+        net_io = psutil.net_io_counters()
+        return {"total_sent": net_io.bytes_sent, "total_recv": net_io.bytes_recv}
+    except Exception:
+        return None
+
+def yandex_internet_speed_test():
+    """
+    Используем API Yandex для проверки скорости Интернета.
+    Функция возвращает скорость загрузки и выгрузки в мегабитах в секунду.
+    """
+    try:
+        # Подставьте ваш уникальный токен Yandex API здесь!
+        headers = {'Authorization': 'Bearer YOUR_YANDEX_API_TOKEN'}
+        response = requests.post(
+            'https://speed.yandex.com/api/v1/test',
+            headers=headers,
+            json={"duration": 10},  # длительность теста, сек
+            timeout=15
+        )
+        response.raise_for_status()
+        results = response.json()
+        download_speed = results.get('download_speed', None)
+        upload_speed = results.get('upload_speed', None)
+        
+        return {
+            "download_speed_mbps": download_speed,
+            "upload_speed_mbps": upload_speed
+        }
+    except Exception as ex:
+        print(f"Произошла ошибка при тестировании скорости: {ex}")
+        return None
+
+def get_ping_and_loss(target, count=4):
+    """Измеряет средний пинг и процент потери пакетов."""
+    try:
+        result = python_ping(target, count=count, timeout=2) 
+        return {"avg_ping_ms": result.rtt_avg_ms, "packet_loss_percent": result.packet_loss}
+    except Exception:
+        return None
+
+def get_local_net_details():
+    """Получает локальный IP, MAC-адрес, имя активного интерфейса и IP шлюза."""
+    details = {"local_ip": None, "mac_address": None, "interface_name": None, "gateway_ip": None}
+    
+    try:
+        gws = netifaces.gateways()
+        default_route = gws.get('default', {}).get(netifaces.AF_INET)
+        
+        if default_route:
+            details['gateway_ip'] = default_route[0]
+            active_interface = default_route[1]
+            details['interface_name'] = active_interface
+
+            addrs = netifaces.ifaddresses(active_interface)
+            
+            if netifaces.AF_INET in addrs:
+                details['local_ip'] = addrs[netifaces.AF_INET][0]['addr']
+                
+            if netifaces.AF_LINK in addrs:
+                details['mac_address'] = addrs[netifaces.AF_LINK][0]['addr'].upper().replace('-', ':')
+
+    except Exception:
+        pass 
+    return details
+
+def get_system_info():
+    """Собирает имя хоста и внешний IP."""
+    info = {"hostname": None, "external_ip": None}
+
+    try:
+        info["hostname"] = socket.gethostname()
+    except:
+        pass
+
+    try:
+        response = requests.get('https://api.ipify.org?format=json', timeout=5)
+        response.raise_for_status()
+        info["external_ip"] = response.json().get('ip')
+    except:
+        pass
+
+    return info
+
+# *** Функции для взаимодействия с базой данных ***
+
+def create_database_and_table(db_file):
+    """
+    Создает базу данных и таблицу NetworkInfo, если они отсутствуют.
+    """
+    conn = sqlite3.connect(db_file)
+    cursor = conn.cursor()
+    
+    # Создание таблицы NetworkInfo
+    cursor.execute('''
+        CREATE TABLE IF NOT EXISTS NetworkInfo (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            hostname TEXT,
+            mac_address TEXT,
+            local_ip TEXT,
+            gateway_ip TEXT,
+            external_ip TEXT,
+            total_sent TEXT,
+            total_recv TEXT,
+            ping_gateway_ms REAL,
+            loss_gateway_percent REAL,
+            ping_ya_ru_ms REAL,
+            loss_ya_ru_percent REAL,
+            download_speed_mbps REAL,
+            upload_speed_mbps REAL,
+            server_name TEXT,
+            server_location TEXT,
+            server_latency REAL,
+            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+        )
+    ''')
+    
+    conn.commit()
+    conn.close()
+
+def save_to_db(db_file, data):
+    """
+    Сохраняет данные в базу данных.
+    """
+    conn = sqlite3.connect(db_file)
+    cursor = conn.cursor()
+    
+    # Заполняем поля из data
+    sql_insert_query = '''
+        INSERT INTO NetworkInfo (
+            hostname, mac_address, local_ip, gateway_ip, external_ip, total_sent, total_recv,
+            ping_gateway_ms, loss_gateway_percent, ping_ya_ru_ms, loss_ya_ru_percent,
+            download_speed_mbps, upload_speed_mbps, server_name, server_location, server_latency
+        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+    '''
+    
+    values = [
+        data.get('hostname'), data.get('mac_address'), data.get('local_ip'),
+        data.get('gateway_ip'), data.get('external_ip'), data.get('total_sent'),
+        data.get('total_recv'), data.get('ping_gateway_ms'), data.get('loss_gateway_percent'),
+        data.get('ping_ya_ru_ms'), data.get('loss_ya_ru_percent'), data.get('download_speed_mbps'),
+        data.get('upload_speed_mbps'), data.get('server_name'), data.get('server_location'),
+        data.get('server_latency')
+    ]
+    
+    cursor.execute(sql_insert_query, values)
+    conn.commit()
+    conn.close()
+
+def view_database(db_file):
+    """
+    Возвращает список всех записей из базы данных.
+    """
+    conn = sqlite3.connect(db_file)
+    cursor = conn.cursor()
+    
+    # Извлекаем все строки из таблицы
+    cursor.execute("SELECT * FROM NetworkInfo ORDER BY created_at ASC;")
+    rows = cursor.fetchall()
+    
+    conn.close()
+    return rows
+
+# *** Графический интерфейс ***
+
+class App(tk.Tk):
+    def __init__(self):
+        super().__init__()
+        self.title("Мониторинг сети")
+        self.geometry("800x600")  # Окно размером 800х600 пикселей
+        self.create_widgets()
+        self.db_file = 'network_reports.db'
+        create_database_and_table(self.db_file)
+
+    def create_widgets(self):
+        frame_buttons = ttk.Frame(self)
+        frame_buttons.pack(pady=(10, 10))
+
+        btn_collect = ttk.Button(frame_buttons, text="Запустить мониторинг", command=self.collect_data)
+        btn_view = ttk.Button(frame_buttons, text="Просмотреть отчёты", command=self.view_reports)
+        btn_exit = ttk.Button(frame_buttons, text="Выход", command=self.quit)
+
+        btn_collect.grid(row=0, column=0, padx=10)
+        btn_view.grid(row=0, column=1, padx=10)
+        btn_exit.grid(row=0, column=2, padx=10)
+
+        # Таблица для просмотра результатов мониторинга
+        columns = ("id", "hostname", "mac_address", "local_ip", "gateway_ip", "external_ip", 
+                  "total_sent", "total_recv", "ping_gateway_ms", "loss_gateway_percent", 
+                  "ping_ya_ru_ms", "loss_ya_ru_percent", "download_speed_mbps", "upload_speed_mbps",
+                  "server_name", "server_location", "server_latency", "created_at")
+        self.tree = ttk.Treeview(self, columns=columns, show="headings")
+        self.tree.pack(fill=tk.BOTH, expand=True)
+
+        for col in columns:
+            self.tree.heading(col, text=col.capitalize(), anchor=tk.W)
+            self.tree.column(col, width=100, stretch=False)
+
+    def collect_data(self):
+        """
+        Собирает всю необходимую информацию и сохраняет её в базу данных.
+        """
+        data = {}
+        target_host = 'ya.ru'
+        output_filename = "network_info_report.txt"
+
+        # Сбор данных
+        print("--- 1. Сбор базовой информации (IP, MAC, Hostname) ---")
+        data.update(get_system_info())
+        data.update(get_local_net_details()) 
+        io_data = get_network_io_total()
+        if io_data:
+            data.update(io_data)
+        print("Базовые данные собраны. ✅")
+
+        # Пинги
+        if data.get('gateway_ip'):
+            print(f"\n--- 2. Проверка пинга до шлюза ({data['gateway_ip']}) ---")
+            ping_gw_data = get_ping_and_loss(data['gateway_ip'])
+            if ping_gw_data:
+                data["ping_gateway_ms"] = ping_gw_data["avg_ping_ms"]
+                data["loss_gateway_percent"] = ping_gw_data["packet_loss_percent"]
+            print("Проверка завершена. 📶")
+
+        print(f"\n--- 3. Проверка пинга до {target_host} ---")
+        ping_ext_data = get_ping_and_loss(target=target_host)
+        if ping_ext_data:
+            data["ping_ya_ru_ms"] = ping_ext_data["avg_ping_ms"]
+            data["loss_ya_ru_percent"] = ping_ext_data["packet_loss_percent"]
+        print("Проверка завершена. 🎯")
+        
+        # Скорость через Yandex SpeedTest
+        print("\n--- 4. Проверка скорости сети (Yandex Speedtest) ---")
+        speed_data = yandex_internet_speed_test()
+        if speed_data:
+            data.update(speed_data)
+            print("Тестирование скорости завершено. 🚀")
+        else:
+            print("Тестирование скорости не выполнено (проверьте интернет-соединение).")
+
+        # Форматирование и вывод отчета
+        report_content = format_report(data, target_host)
+        
+        print(report_content)
+        
+        try:
+            with open(output_filename, 'w', encoding='utf-8') as f:
+                f.write(report_content)
+            print(f"\n✅ Отчет успешно сохранен в файле: {output_filename} в папке {os.getcwd()}")
+        except Exception as e:
+            print(f"\n❌ Ошибка при записи отчета в файл: {e}")
+
+        # Сохраняем данные в базу данных
+        save_to_db(self.db_file, data)
+        messagebox.showinfo("Готово", "Данные успешно собраны и сохранены!")
+
+    def view_reports(self):
+        """
+        Загружает и показывает данные из базы данных в таблице.
+        """
+        rows = view_database(self.db_file)
+        self.tree.delete(*self.tree.get_children())
+        for row in rows:
+            self.tree.insert("", tk.END, values=row)
+
+if __name__ == "__main__":
+    app = App()
+    app.mainloop()