How to bring get request parameters into streamlit app

I’ve got a simple streamlit app that accepts get parameters in the browser bar, but it will not report parameters from a command line call, for example using curl.

curl reports a successful interaction but nothing shows up in the streamlit app.

how can I make get request parameters show up in streamlit from the command line?

screenshot with successful get parameters received from browser:

curl command line get request sender:

curl "http://localhost:8501/?message=TestMessage"

example streamlit app:

import time
from datetime import datetime
import streamlit as st

st.title("Streamlit test_app.py")
message_container = st.empty()

# Style for the bars
st.markdown("""
<style>
    .message-bar {
        background-color: #fce4b7;
        color: #000;
        font-size: 18px;
        text-align: center;
        padding: 10px 0;
        border-radius: 5px;
        margin-top: 20px;
    }
</style>
""", unsafe_allow_html=True)

def display_message_from_query():
    nowStr = datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
    query_params = st.query_params
    print(f'query_params={query_params}')
    if len(query_params)>0:
        recvTimeStr = datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
        message = query_params  # This returns a list
        #full_message = message if message else "No message provided"
        print(f"[{recvTimeStr}] Received message: {message}")
        message_container.markdown(
            f'<div class="message-bar">### Received Message: {message} at {recvTimeStr}</div>',
            unsafe_allow_html=True,
        )
    else:
        print(f"[{nowStr}] No 'message' query parameter found.")
        message_container.markdown(
            f'<div class="message-bar">### No message received yet.</div>',
            unsafe_allow_html=True,
        )
    


def loop():
    display_message_from_query()

if __name__ == "__main__":
    while True:
        loop()
        time.sleep(1)
1 Like

Query parameters are tied to a particular session, so if you access the app from your command line it won’t have any impact on another session you are viewing in a browser tab. Streamlit runs on a Tornado server (HTTP + WebSocket). Each connection is a distinct session. If you are viewing the app from two different browser tabs, they don’t know anything about each others’ query parameters.

To step back a level, what are you trying accomplish with these messages?

1 Like

hello, this is helpful.

I’m trying to bring in about 8 to 12 numbers from a weather station, live, straight from the sensors.

so if I can figure out how to get the data from behind my university firewall into the streamlit community cloud app, it’ll need to be delivered in a way that is persistent across multiple sessions.

there are a few examples on persistent session states, but that’s not my current problem.

the first issue is access to streaming data, live, with updates around every second. it’s a straightforward http get or even a udp message, but these are disallowed.

the streaming case seems to be something that streamlit has avoided :thinking::man_shrugging:

It is not clear to me how the API of the weather stations works. I’m picturing a recurring st.fragment (i.e. with the run_every argument) that makes a request of the data. Is that kind of HTTP request not possible?

By streaming, you mean the weather station writing to some database (external to Streamlit Cloud), which then is queried by the webapp?

well, the raspberry pi is behind a firewall. it has outbound access but no inbound access. establishing a two-way communication channel, like a websocket, would be ideal because it provides a tcp connection over standard http ports. I’ve never used websockets before and am exploring them. if a websocket can be initiated by the pi, then either side could determine the data transfer interval.

there is no storage strictly necessary to display current sensor data, but a small history of 10 or 50 points wouldn’t be too difficult using session state.

the st.fragment method could be helpful. I’d rather have a periodic callback (a callback timer) rather than a button.

the pi has the data directly from the sensors, so delivering the latest array of floating point numbers is as straightforward as websocket.send()'ing them in the websocket connection with a framing terminator so the streamlit side knows when the message is complete.

the pi API can be made however. sending directly from sensors to the streamlit app is the goal. I don’t see any need for an intermediate database. that would add an extra unecesssry step.

I’ve got the command line sender and streamlit receiver working working with flask but the community cloud doesn’t support flask.

the challenge is to go establish an open connection between the two computers with firewall restrictions

That’s why I thought of the raspberry pi writing to an external database from which the web app reads every so often. Presumably, you will want the historical data of the sensors as well. I understand why you’d want a direct communication between sensors and app, but I suspect writing to/reading from a database every 5s or so will not add a considerable overhead.

Every user have their own session state, but the current data should be the same for all users. You perhaps want to update a cached resource (st.cache_resource - Streamlit Docs), setting the ttl argument to some time step the app would refresh with new data.

Try to send sensor values thrue MQTT protocol, and catch them in the MQTT broker. MQTT is designed for this job :slightly_smiling_face:

MQTT is a pretty good idea, but there seem to be no clear, simple examples with Streamlit and the Community Cloud.

Do you have a simple example of an MQTT client connecting to a running streamlit app on the Community Cloud?

@edsaac, I’ve got the historical data figured out.

I’m looking for real time updates with no intermediate storage.

Once the sensors get data, they should be displayed on a streamlit app on the community cloud and displayed within just a few milliseconds.

so far this is not straightforward. :person_shrugging: :thinking:

I created a GitHub issue to request an endpoint that might help in this kind of scenario if anyone is interested and wants to upvote it:

3 Likes

Very important function.

It’s an excellent contribution to the streamlit API and community.

I’ve up voted.

Also, I’ve been experimenting with websockets for streamlit real time updates via a command line client who is behind a firewall.

I’ll post the app and client just as soon as it’s ready. It’s looking good so far.

thank you