Streamlit live updating plot

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()

Hi @darynella2001

You could make use of the sleep method from the time module together with a for loop to iteratively update the plot every N seconds (e.g. time.sleep(1))

Here are some relevant posts to get you started:

This blog also has an example that you can use a starter idea:

Hope these helps!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.