Files
2026-10-06 21:08:12 +03:00

370 lines
6.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Статистика базы данных WiFi GPS Mapper.
Этот модуль ничего не рисует.
Он только собирает информацию из SQLite и
возвращает обычные словари Python.
Отображением занимается dashboard.py.
"""
from pathlib import Path
from .config import (
DATABASE_FILE,
CAPTURES_DIR,
)
from .database import (
query_value,
query_one,
)
from .utils import (
format_size,
)
# ============================================================
# Размер базы
# ============================================================
def database_size():
if not DATABASE_FILE.exists():
return 0
return DATABASE_FILE.stat().st_size
# ============================================================
# Размер каталога
# ============================================================
def directory_size(path):
path = Path(path)
if not path.exists():
return 0
total = 0
for file in path.rglob("*"):
if file.is_file():
total += file.stat().st_size
return total
# ============================================================
# Количество файлов
# ============================================================
def count_files(path):
path = Path(path)
if not path.exists():
return 0
total = 0
for file in path.rglob("*"):
if file.is_file():
total += 1
return total
# ============================================================
# Общая статистика
# ============================================================
def database_statistics(conn):
statistics = {}
statistics["access_points"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM access_points
""",
default=0
)
statistics["access_points_without_coordinates"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM access_points
WHERE
last_latitude IS NULL
OR last_longitude IS NULL
""",
default=0
)
statistics["vendors"] = query_value(
conn,
"""
SELECT COUNT(DISTINCT vendor)
FROM access_points
WHERE vendor IS NOT NULL
AND vendor!=''
""",
default=0
)
statistics["sessions"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM capture_sessions
""",
default=0
)
statistics["handshakes"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM handshakes
""",
default=0
)
statistics["credentials"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM credentials
""",
default=0
)
statistics["pmkid"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM access_points
WHERE has_pmkid=1
""",
default=0
)
statistics["cracked"] = query_value(
conn,
"""
SELECT COUNT(*)
FROM access_points
WHERE is_cracked=1
""",
default=0
)
statistics["capture_files"] = count_files(
CAPTURES_DIR
)
statistics["database_size"] = format_size(
database_size()
)
statistics["captures_size"] = format_size(
directory_size(
CAPTURES_DIR
)
)
row = query_one(
conn,
"""
SELECT
MIN(first_seen),
MAX(last_seen)
FROM access_points
"""
)
if row:
statistics["first_seen"] = row[0]
statistics["last_seen"] = row[1]
else:
statistics["first_seen"] = None
statistics["last_seen"] = None
return statistics
# ============================================================
# Статистика производителей
# ============================================================
def top_vendors(
conn,
limit=20
):
sql = """
SELECT
vendor,
COUNT(*) AS devices
FROM access_points
WHERE vendor IS NOT NULL
AND vendor!=''
GROUP BY vendor
ORDER BY devices DESC
LIMIT ?
"""
return conn.execute(
sql,
(
limit,
)
).fetchall()
# ============================================================
# Используемые каналы
# ============================================================
def channel_statistics(conn):
sql = """
SELECT
channel,
COUNT(*) AS total
FROM access_points
GROUP BY channel
ORDER BY channel
"""
return conn.execute(sql).fetchall()
# ============================================================
# Типы шифрования
# ============================================================
def encryption_statistics(conn):
sql = """
SELECT
encryption,
COUNT(*) AS total
FROM access_points
GROUP BY encryption
ORDER BY total DESC
"""
return conn.execute(sql).fetchall()
# ============================================================
# Самые часто встречающиеся ESSID
# ============================================================
def top_essid(
conn,
limit=25
):
sql = """
SELECT
essid,
COUNT(*) AS total
FROM access_points
WHERE essid IS NOT NULL
AND essid!=''
GROUP BY essid
ORDER BY total DESC
LIMIT ?
"""
return conn.execute(
sql,
(
limit,
)
).fetchall()
# ============================================================
# Самые сильные сигналы
# ============================================================
def strongest_access_points(
conn,
limit=20
):
sql = """
SELECT
bssid,
essid,
vendor,
last_rssi
FROM access_points
ORDER BY last_rssi DESC
LIMIT ?
"""
return conn.execute(
sql,
(
limit,
)
).fetchall()