|
import streamlit as st |
|
import pandas as pd |
|
import numpy as np |
|
import plotly.express as px |
|
from sklearn.ensemble import IsolationForest |
|
from io import BytesIO |
|
from reportlab.lib.pagesizes import letter |
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak |
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle |
|
from reportlab.lib.units import inch |
|
from reportlab.lib import colors |
|
import pdfplumber |
|
import base64 |
|
import random |
|
import plotly.io as pio |
|
|
|
|
|
pio.kaleido.scope.mathjax = None |
|
|
|
|
|
st.set_page_config( |
|
page_title="WiFi Guardian π‘οΈ", |
|
page_icon="πΆ", |
|
layout="wide" |
|
) |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.st-emotion-cache-1kyxreq { |
|
display: flex; |
|
flex-flow: wrap; |
|
gap: 2rem; |
|
} |
|
.reportview-container .main .block-container{ |
|
padding-top: 2rem; |
|
} |
|
.sidebar .sidebar-content { |
|
background: linear-gradient(180deg, #2e3b4e, #1a2639); |
|
} |
|
.stButton>button { |
|
width: 100%; |
|
margin: 5px 0; |
|
transition: all 0.3s; |
|
} |
|
.stButton>button:hover { |
|
transform: scale(1.05); |
|
} |
|
.summary-box { |
|
padding: 20px; |
|
border-radius: 10px; |
|
background-color: #2e3b4e; |
|
margin: 10px 0; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
QUOTES = [ |
|
"π‘οΈ Cybersecurity is not a product, but a process!", |
|
"π Better safe than hacked!", |
|
"πΆ A secure network is a happy network!", |
|
"π€ AI guards while you sleep!", |
|
"π¨ Detect before you regret!", |
|
"π» Security is always worth the investment!", |
|
"π Stay vigilant, stay secure!" |
|
] |
|
|
|
def show_quote(): |
|
st.markdown(f"<h3 style='text-align: center; color: #4CAF50;'>{random.choice(QUOTES)}</h3>", |
|
unsafe_allow_html=True) |
|
|
|
|
|
def main(): |
|
|
|
if 'current_step' not in st.session_state: |
|
st.session_state.current_step = 1 |
|
if 'file_uploaded' not in st.session_state: |
|
st.session_state.file_uploaded = False |
|
if 'df' not in st.session_state: |
|
st.session_state.df = None |
|
|
|
|
|
with st.sidebar: |
|
st.title("π Navigation") |
|
st.markdown("---") |
|
|
|
if st.button("π€ 1. Upload File", help="Upload your network logs"): |
|
st.session_state.current_step = 1 |
|
if st.button("π 2. Data Visualization", disabled=not st.session_state.file_uploaded): |
|
st.session_state.current_step = 2 |
|
if st.button("π 3. Statistics Analysis", disabled=not st.session_state.file_uploaded): |
|
st.session_state.current_step = 3 |
|
if st.button("π₯ 4. Download Report", disabled=not st.session_state.file_uploaded): |
|
st.session_state.current_step = 4 |
|
|
|
|
|
if st.session_state.current_step == 1: |
|
upload_file_section() |
|
elif st.session_state.current_step == 2: |
|
visualization_section() |
|
elif st.session_state.current_step == 3: |
|
statistics_section() |
|
elif st.session_state.current_step == 4: |
|
download_section() |
|
|
|
def upload_file_section(): |
|
st.title("π€ Upload Network Logs") |
|
st.markdown("---") |
|
|
|
if not st.session_state.file_uploaded: |
|
show_quote() |
|
st.markdown(""" |
|
### Welcome to WiFi Guardian! π€ |
|
**Protect your network with AI-powered anomaly detection** |
|
1. Upload network logs π€ |
|
2. Visualize patterns π |
|
3. Generate reports π |
|
""") |
|
|
|
uploaded_file = st.file_uploader( |
|
"Choose network logs (CSV/TXT/PDF)", |
|
type=["csv", "txt", "pdf"], |
|
label_visibility="collapsed" |
|
) |
|
|
|
if uploaded_file: |
|
try: |
|
process_file(uploaded_file) |
|
st.session_state.file_uploaded = True |
|
st.success("β
File processed successfully!") |
|
|
|
|
|
st.subheader("π Upload Summary") |
|
col1, col2, col3 = st.columns(3) |
|
with col1: |
|
st.metric("Total Records", len(st.session_state.df)) |
|
with col2: |
|
anomalies = sum(st.session_state.df['anomaly'] == -1) |
|
st.metric("Anomalies Detected", f"{anomalies} ({anomalies/len(st.session_state.df)*100:.1f}%)") |
|
with col3: |
|
st.metric("Max Traffic", f"{st.session_state.df['traffic'].max():.2f} Mbps") |
|
|
|
except Exception as e: |
|
st.error(f"Error processing file: {str(e)}") |
|
|
|
def visualization_section(): |
|
st.title("π Data Visualization") |
|
st.markdown("---") |
|
|
|
|
|
st.subheader("2D Traffic Analysis π") |
|
|
|
df = st.session_state.df.copy() |
|
if 'timestamp' not in df.columns: |
|
df['timestamp'] = pd.date_range(start="2021-01-01", periods=len(df), freq="T") |
|
fig2d = px.scatter( |
|
df, |
|
x='timestamp', |
|
y='traffic', |
|
color='anomaly', |
|
color_discrete_map={-1: 'orange', 1: 'blue'}, |
|
title="2D Traffic Analysis" |
|
) |
|
st.plotly_chart(fig2d, use_container_width=True) |
|
|
|
|
|
st.subheader("3D Network Health π") |
|
fig3d = px.scatter_3d( |
|
df, |
|
x='latency', |
|
y='packet_loss', |
|
z='traffic', |
|
color='anomaly', |
|
color_discrete_map={-1: 'orange', 1: 'blue'}, |
|
title="3D Network Analysis" |
|
) |
|
st.plotly_chart(fig3d, use_container_width=True) |
|
|
|
def statistics_section(): |
|
st.title("π Statistical Analysis") |
|
st.markdown("---") |
|
|
|
st.subheader("Data Summary π") |
|
st.dataframe(st.session_state.df.describe(), use_container_width=True) |
|
|
|
st.subheader("Anomaly Distribution π") |
|
anomaly_counts = st.session_state.df['anomaly'].value_counts() |
|
fig = px.pie( |
|
names=['Normal', 'Anomaly'], |
|
values=[anomaly_counts.get(1, 0), anomaly_counts.get(-1, 0)], |
|
hole=0.4, |
|
color_discrete_sequence=['blue', 'orange'], |
|
title="Anomaly Distribution" |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
def download_section(): |
|
st.title("π₯ Download Report") |
|
st.markdown("---") |
|
|
|
if st.button("π¨οΈ Generate Full Report"): |
|
with st.spinner("Generating PDF report..."): |
|
generate_pdf_report() |
|
st.success("Report generated successfully!") |
|
|
|
if 'pdf_report' in st.session_state: |
|
st.markdown("---") |
|
b64 = base64.b64encode(st.session_state.pdf_report).decode() |
|
href = f'<a href="data:application/octet-stream;base64,{b64}" download="wifi_report.pdf">π₯ Download Full Report</a>' |
|
st.markdown(href, unsafe_allow_html=True) |
|
|
|
def process_file(uploaded_file): |
|
try: |
|
|
|
if uploaded_file.name.endswith('.csv'): |
|
df = pd.read_csv(uploaded_file) |
|
|
|
elif uploaded_file.name.endswith('.txt'): |
|
lines = [line.decode().strip().split(',') for line in uploaded_file.readlines()] |
|
df = pd.DataFrame(lines[1:], columns=lines[0]) |
|
|
|
elif uploaded_file.name.endswith('.pdf'): |
|
with pdfplumber.open(uploaded_file) as pdf: |
|
text = '\n'.join([page.extract_text() for page in pdf.pages]) |
|
lines = [line.split(',') for line in text.split('\n') if line] |
|
df = pd.DataFrame(lines[1:], columns=lines[0]) |
|
else: |
|
raise ValueError("Unsupported file type.") |
|
|
|
|
|
numeric_cols = ['traffic', 'latency', 'packet_loss'] |
|
for col in numeric_cols: |
|
if col not in df.columns: |
|
raise ValueError(f"Column '{col}' not found in data.") |
|
df[col] = pd.to_numeric(df[col], errors='coerce') |
|
|
|
|
|
clf = IsolationForest(contamination=0.4, random_state=42) |
|
df['anomaly'] = clf.fit_predict(df[numeric_cols]) |
|
|
|
st.session_state.df = df |
|
|
|
except Exception as e: |
|
st.error(f"Error processing file: {str(e)}") |
|
raise |
|
|
|
def generate_pdf_report(): |
|
try: |
|
buffer = BytesIO() |
|
doc = SimpleDocTemplate(buffer, pagesize=letter) |
|
styles = getSampleStyleSheet() |
|
elements = [] |
|
|
|
|
|
title_style = ParagraphStyle( |
|
name='Title', |
|
parent=styles['Heading1'], |
|
fontSize=18, |
|
textColor=colors.darkblue, |
|
spaceAfter=14 |
|
) |
|
|
|
|
|
elements.append(Paragraph("WiFi Network Anomaly Detection", title_style)) |
|
elements.append(Spacer(1, 12)) |
|
|
|
|
|
elements.append(Paragraph("<b>Detection Summary:</b>", styles['Heading2'])) |
|
summary_text = f""" |
|
β’ Total Data Points: {len(st.session_state.df)}<br/> |
|
β’ Anomalies Detected: {sum(st.session_state.df['anomaly'] == -1)}<br/> |
|
β’ Maximum Traffic: {st.session_state.df['traffic'].max():.2f} Mbps<br/> |
|
β’ Average Latency: {st.session_state.df['latency'].mean():.2f} ms<br/> |
|
β’ Peak Packet Loss: {st.session_state.df['packet_loss'].max():.2f}%<br/> |
|
""" |
|
elements.append(Paragraph(summary_text, styles['BodyText'])) |
|
elements.append(PageBreak()) |
|
|
|
|
|
|
|
|
|
df = st.session_state.df.copy() |
|
if 'timestamp' not in df.columns: |
|
df['timestamp'] = pd.date_range(start="2021-01-01", periods=len(df), freq="T") |
|
fig2d = px.scatter(df, x='timestamp', y='traffic', |
|
color='anomaly', title="2D Traffic Analysis", |
|
color_discrete_map={-1: 'orange', 1: 'blue'}) |
|
img_bytes_2d = fig2d.to_image(format="png", engine="kaleido") |
|
img2d_io = BytesIO(img_bytes_2d) |
|
|
|
|
|
fig3d = px.scatter_3d(df, x='latency', y='packet_loss', |
|
z='traffic', color='anomaly', title="3D Network Analysis", |
|
color_discrete_map={-1: 'orange', 1: 'blue'}) |
|
img_bytes_3d = fig3d.to_image(format="png", engine="kaleido") |
|
img3d_io = BytesIO(img_bytes_3d) |
|
|
|
|
|
elements.append(Paragraph("<b>2D Traffic Analysis</b>", styles['Heading2'])) |
|
elements.append(Image(img2d_io, width=6*inch, height=4*inch)) |
|
elements.append(Spacer(1, 12)) |
|
|
|
|
|
elements.append(Paragraph("<b>3D Network Analysis</b>", styles['Heading2'])) |
|
elements.append(Image(img3d_io, width=6*inch, height=4*inch)) |
|
elements.append(PageBreak()) |
|
|
|
|
|
elements.append(Paragraph("<b>Statistical Report</b>", styles['Heading1'])) |
|
stats = st.session_state.df.describe() |
|
for col in ['traffic', 'latency', 'packet_loss']: |
|
elements.append(Paragraph(f"<b>{col.capitalize()} Statistics:</b>", styles['Heading3'])) |
|
stats_text = f""" |
|
β’ Mean: {stats[col]['mean']:.2f}<br/> |
|
β’ Std Dev: {stats[col]['std']:.2f}<br/> |
|
β’ Min: {stats[col]['min']:.2f}<br/> |
|
β’ 25%: {stats[col]['25%']:.2f}<br/> |
|
β’ 50%: {stats[col]['50%']:.2f}<br/> |
|
β’ 75%: {stats[col]['75%']:.2f}<br/> |
|
β’ Max: {stats[col]['max']:.2f}<br/> |
|
""" |
|
elements.append(Paragraph(stats_text, styles['BodyText'])) |
|
elements.append(Spacer(1, 12)) |
|
|
|
doc.build(elements) |
|
st.session_state.pdf_report = buffer.getvalue() |
|
|
|
except Exception as e: |
|
st.error(f"Error generating report: {str(e)}") |
|
|
|
if __name__ == "__main__": |
|
main() |
|
|