A Simple Data Visualization Web App Using Streamlit Library

The concept of the Internet of Things (IoT) revolves around the integration of sensors with compact computing devices like Arduino boards. This fusion enables a multitude of applications, ranging from surveillance monitoring to automated door locking and smart farming. A pivotal component of IoT systems is the dashboard, which serves as a hub for visualizing incoming data streams.

Consider, for instance, an automated aquaponics system. Monitoring various parameters such as water levels, temperature, and dissolved oxygen levels is crucial for its efficient operation. Having a dashboard where users can effortlessly observe these sensor readings is paramount for informed decision-making.

Beyond visualization, the next step in the data acquisition process often involves storing this information in databases for future analysis. However, for simpler projects requiring only recent data, there’s no imperative to store data in databases. This streamlined approach simplifies project implementation and reduces overhead.

In this tutorial, we’ll delve into harnessing the power of Python and Streamlit, a versatile library, to craft Data Visualization Web App for visualizing sensor data. Unlike conventional methods that necessitate database storage, our focus will be on preserving sensor data in the program’s dynamic memory for a limited duration, catering to real-time monitoring needs. Let’s embark on a journey through the following code blocks, unraveling the steps to construct this project.

Our project aims to create a system that can read temperature and humidity data from a sensor connected to a microcontroller and visualize it in real-time. To accomplish this, we’ll be using Python along with some popular libraries such as serial, numpy, pandas, altair, and streamlit.

Setting Up the Hardware

Before diving into the code, let’s briefly discuss the hardware setup. We’ll need a temperature and humidity sensor connected to a microcontroller. In our example, we’ll assume the sensor is connected to the USB port of your computer, but you can adapt the code for other setups accordingly. For the purpose of demonstration, we will use a simple function to generate synthetic data similiar to sensors.

Understanding the Code

Let’s break down the key components of the code provided:

Importing Libraries: We start by importing necessary libraries including serial for serial communication, numpy and pandas for data manipulation, altair for visualization, streamlit for building interactive web apps, and datetime for timestamping.

import serial
import numpy as np
import pandas as pd
import altair as alt
from time import sleep
import streamlit as st
from datetime import datetime
from serial.tools import list_ports

As a next step we will set the port name and baud rate.

ser = None
DEVICE_NAME = "/dev/ttyUSB0"
BAUD_RATE = 9600

Finding the Device: The find_device() function searches for the connected device by iterating through available ports.

def find_device():
    devices = list_ports.comports()
    for device in devices:
        if DEVICE_NAME in device.device:
            return device.device
    return None

Custom Functions: We define functions like dummy_read_from_device() and custom_chart() to simulate data reading and customize charts, respectively.

def dummy_read_from_device(ser):
    dt_now = datetime.now()
    temperature = np.random.randn(1)[0]
    humidity = np.random.randn(1)[0]
    sleep(1)
    return dt_now, temperature, humidity


def custom_chart(data, x, y, color, ylabel):
    base = alt.Chart(data).encode(
        x=x, y=alt.Y(y, axis=alt.Axis(title=ylabel))  # Set the y-label here
    )
    return base.mark_line().encode(color=color)

Here the function dummy_read_from_device() is used for generating synthetic data so that we can test the code even without sensors connected via the USB port. The purpose of custom_chart() function is to add provision to give custom y-labels to the sensor data charts being displayed.

Reading from the Device: The read_from_device() function reads data from the serial device, parses it, and returns the temperature and humidity values.

def read_from_device(ser):
    if ser is not None and ser.isOpen():
        try:
            line = ser.readline().decode("utf-8").rstrip()
            print("Received line:", line)
            parts = line.split(",")

            if len(parts) >= 2:
                temperature_str = parts[0].split(":")[1].replace("C", "").strip()
                humidity_str_with_rssi = parts[1].split(":")[1].replace("%", "").strip()
                humidity_str = humidity_str_with_rssi.split("'")[0]
                dt_now = datetime.now()
                temperature = float(temperature_str)
                humidity = float(humidity_str)
                return dt_now, temperature, humidity
            else:
                print("Error: Received line does not have expected format")
                return None, None, None
        except Exception as e:
            print(f"Error reading from the serial device: {e}")
            return None, None, None
    else:
        print("Serial device is not open or disconnected.")
        return None, None, None

Here the function read_from_device() is the core part of the program which reads string data that is coming through the serial port, parse it, apply necessary type conversion and returns it. If the sensors and arduino boards are not available to you, then you can use the dummy_read_from_device() function discussed earlier instead of this.

Main Function: In the main block, we continuously read data from the device, update the DataFrame, and visualize it using Streamlit

if __name__ == "__main__":
    device_name = find_device()
    if device_name:
        ser = serial.Serial(device_name, BAUD_RATE)
        while True:
            result_df = pd.DataFrame(columns=["time", "temperature", "humidity"])
            st.title("Temperature-Humidity Monitoring")
            temp_graph_holder = st.empty()
            humid_graph_holder = st.empty()
            num_points = 20
            i = 0
            while True:
                dt_now, temperature, humidity = read_from_device(ser)
                if dt_now:
                    row = {
                        "time": dt_now,
                        "temperature": temperature,
                        "humidity": humidity,
                    }
                    result_df.loc[i % num_points] = row
                    result_df["time"] = pd.to_datetime(result_df["time"])
                    result_df["time"] = result_df["time"].dt.strftime("%H:%M:%S")
                    i += 1
                    if result_df.shape[0] > 0:
                        temp_chart = custom_chart(
                            result_df,
                            x="time",
                            y="temperature",
                            color=alt.value("#FFFF00"),
                            ylabel="Temperature (°C)",
                        )
                        temp_graph_holder.altair_chart(
                            temp_chart, use_container_width=True
                        )

                        humid_chart = custom_chart(
                            result_df,
                            x="time",
                            y="humidity",
                            color=alt.value("#0000FF"),
                            ylabel="Humidity (%)",
                        )
                        humid_graph_holder.altair_chart(
                            humid_chart, use_container_width=True
                        )
                else:
                    continue
    else:
        print("No serial device found.")

Running the Code

To run the code:

  • Connect your sensor to the computer.
  • Ensure the correct device name and baud rate are set in the code.
  • Execute the Python script. To execute, type streamlit run app.py in the terminal.

Visualizing the Data

Once the script is running, you’ll see two charts displayed using Streamlit: one for temperature and another for humidity. These charts will update in real-time as new data is received from the sensor.

Conclusion

In this article, we’ve demonstrated how to build a temperature-humidity monitoring system using Python. By leveraging the power of Python libraries and hardware components, you can create sophisticated monitoring systems tailored to your specific needs. This project, Data Visualization Web App serves as a foundation for further exploration into IoT (Internet of Things) applications and data visualization techniques. So, grab your sensors and start monitoring the world around you!

Leave a Comment

Your email address will not be published. Required fields are marked *