Hi,
I am trying to deploy a streamlit app and a websocket server on Heroku and I have been able to successfully do the same. However, the error occurs once I have made the deployment. When I open the Heroku app and check the logs from both the dynos (I have 2 dynos: web and worker). The worker dyno runs the websocket server. According to the logs the web application is unable to send any requests to the websocket server. I have also confirmed that the address I am connecting to in the app is the correct one. Please let me know where I am going wrong given this is the first deployment I am making.
Here is the code for my websocket_server.py
import os
import asyncio
import websockets
import signal
CONNECTED_CLIENTS = set()
async def handler(websocket, path):
CONNECTED_CLIENTS.add(websocket)
print(f"Client connected: {websocket.remote_address}")
try:
async for message in websocket:
print(f"Received message: {message}")
for client in CONNECTED_CLIENTS:
if client != websocket and client.open:
await client.send(message)
finally:
CONNECTED_CLIENTS.remove(websocket)
print(f"Client disconnected: {websocket.remote_address}")
async def main():
loop = asyncio.get_running_loop()
stop = loop.create_future()
loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)
port = int(os.environ.get("PORT", "8001"))
async with websockets.serve(handler, "", port):
print(f"WebSocket server started on :{port}")
await stop
if __name__ == "__main__":
asyncio.run(main())
Here is the code for my streamlit app:
import streamlit as st
import asyncio
import websockets
async def send_command(command):
try:
async with websockets.connect("wss://hololens-sense-9bd80b459134.herokuapp.com/") as websocket:
await websocket.send(command)
print(f"Sent command : {command}")
except Exception as e:
print(f"Error sending command: {e}")
def send_command_async(command):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(send_command(command))
st.title("Remote Control for HoloLens")
col1, col2 = st.columns([3, 1])
with st.container():
with col1:
if st.button("Increase Distance"):
send_command_async("increase_distance")
if st.button("Decrease Distance"):
send_command_async("decrease_distance")
if st.button("Toggle Left"):
send_command_async("toggle_left")
st.subheader("Increase Quad Size")
left_slider = st.slider("Select aspect ratio of Quad", min_value=0.0, max_value=1.0, value=0.5, step=0.01)
st.write(f"Quad Aspect Ratio: {left_slider}")
st.subheader("Change Filter Mode")
if st.button("Filter Point"):
send_command_async("filter_point")
if st.button("Filter Bilinear"):
send_command_async("filter_bilinear")
if st.button("Filter Trilinear"):
send_command_async("filter_trilinear")
if st.button("Toggle Grayscale"):
send_command_async("toggle_grayscale")
with col2:
st.write("")
if st.button("⬆️ Up"):
send_command_async("move_up")
col2_left, col2_right = st.columns(2)
with col2_left:
if st.button("⬅️ Left"):
send_command_async("move_left")
with col2_right:
if st.button("➡️ Right"):
send_command_async("move_right")
st.write("") # Add some space below the buttons
if st.button("⬇️ Down"):
send_command_async("move_down")
st.subheader("Move Quad to Position")
if st.button("Bottom Left"):
send_command_async("bottom_left")
if st.button("Bottom Right"):
send_command_async("bottom_right")
if st.button("Top Left"):
send_command_async("top_left")
if st.button("Top Right"):
send_command_async("top_right")
if st.session_state.get('previous_slider_value') != left_slider:
st.session_state['previous_slider_value'] = left_slider
send_command_async(f"slider_value:{left_slider}")
Here is the setup.sh file and Procfile:
mkdir -p ~/.streamlit/
echo "\
[general]\n\
email = \"your-email@domain.com\"\n\
" > ~/.streamlit/credentials.toml
echo "\
[server]\n\
headless = true\n\
port = $PORT\n\
enableCORS = false\n\
\n\
" > ~/.streamlit/config.toml
web: sh setup.sh && streamlit run app.py --server.port=$PORT
worker: python websocket_server.py