Hello!
I am working on a Streamlit app which goal is to have a figure with live-updating data. To give more context, I sniff some network packets and I want to plot them in a graph/figure/plot. Also, I want to refresh and re-plot the data every X amount of time. (let’s say every 1s). How can I do it. Until now, my code plots one figure per sniffed packet.
import streamlit as st
import psutil
from scapy.all import *
import matplotlib.pyplot as plt
timestamps = []
packet_sizes = []
fig, ax = plt.subplots()
line, = ax.plot([], [], label='Packet Size')
def get_interface_details(interface):
try:
addresses = psutil.net_if_addrs()
if interface in addresses:
ip_address = addresses[interface][0].address
netmask = addresses[interface][0].netmask
details = f"Interface: {interface}\nIP Address: {ip_address}\nNetmask: {netmask}"
return details
except:
return interface
def get_available_interfaces():
interfaces = []
for interface, addresses in psutil.net_if_addrs().items():
if interface != "lo":
interface_details = get_interface_details(interface)
interfaces.append(interface_details)
return interfaces
def packet_handler(packet):
if Dot1Q in packet and packet[Dot1Q].prio==7:
packet_len = len(packet)
packet_time = packet.time
update_plot(packet_time, packet_len)
st.pyplot(fig)
def start_sniffing(interface):
st.write("Starting packet capture on interface", interface)
sniff(iface=interface, prn=packet_handler)
def update_plot(timestamp, packet_size):
timestamps.append(timestamp)
packet_sizes.append(packet_size)
line.set_xdata(timestamps)
line.set_ydata(packet_sizes)
ax.relim()
ax.autoscale_view()
def main():
st.set_page_config(page_title="Network Analyzer (Protocol & Speed Test)")
st.title("Network Analyzer (Protocol & Speed Test)")
# Add custom CSS style for the page background
page_bg_img = '''
<style>
.stApp {
backgrou-color:white;
background-size: cover;
}
</style>
'''
st.markdown(page_bg_img, unsafe_allow_html=True)
interfaces = get_available_interfaces()
if not interfaces:
st.error("No network interfaces found.")
return
selected_interface = st.selectbox("Select an interface", interfaces, format_func=lambda x: x.replace('\n', ', '))
if st.button("Start Capture"):
interface_name = selected_interface.split('\n')[0].split(": ")[1] # Extract the interface name from the selected option
start_sniffing(interface_name)
if __name__ == "__main__":
main()