sgbaird commited on
Commit
7385f67
·
1 Parent(s): 811d699

app backup

Browse files
Files changed (1) hide show
  1. app_backup.py +187 -0
app_backup.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import queue
3
+ import time
4
+ import secrets
5
+
6
+ import paho.mqtt.client as mqtt
7
+ import streamlit as st
8
+ import matplotlib.pyplot as plt
9
+
10
+ # Initialize Streamlit app
11
+ st.title("Motor Control Panel")
12
+
13
+ # Description and context
14
+ st.markdown(
15
+ """
16
+ This application accesses a public test demo of a motor control located in
17
+ Toronto, ON, Canada (as of 2024-07-27). Send speed commands to the motor and
18
+ visualize the RPM data.
19
+
20
+ For more context, you
21
+ can refer to this [Colab
22
+ notebook](https://colab.research.google.com/github/sparks-baird/self-driving-lab-demo/blob/main/notebooks/4.2-paho-mqtt-colab-sdl-demo-test.ipynb)
23
+ and the [self-driving-lab-demo
24
+ project](https://github.com/sparks-baird/self-driving-lab-demo). You may also be
25
+ interested in the Acceleration Consortium's ["Hello World"
26
+ microcourse](https://ac-microcourses.readthedocs.io/en/latest/courses/hello-world/index.html)
27
+ for self-driving labs.
28
+ """
29
+ )
30
+
31
+ with st.form("mqtt_form"):
32
+
33
+ # MQTT Configuration
34
+ HIVEMQ_HOST = st.text_input(
35
+ "Enter your HiveMQ host:",
36
+ "248cc294c37642359297f75b7b023374.s2.eu.hivemq.cloud",
37
+ type="password",
38
+ )
39
+ HIVEMQ_USERNAME = st.text_input("Enter your HiveMQ username:", "sgbaird")
40
+ HIVEMQ_PASSWORD = st.text_input(
41
+ "Enter your HiveMQ password:", "D.Pq5gYtejYbU#L", type="password"
42
+ )
43
+ PORT = st.number_input(
44
+ "Enter the port number:", min_value=1, max_value=65535, value=8883
45
+ )
46
+
47
+ # User input for the Pico ID
48
+ PICO_ID = st.text_input("Enter your Pico ID:", "test-fan", type="password")
49
+
50
+ # Sliders for speed values
51
+ speed = st.slider("Select the Speed value:", min_value=0, max_value=100, value=0)
52
+
53
+ submit_button = st.form_submit_button(label="Send Speed Command")
54
+
55
+ command_topic = f"sdl-demo/picow/{PICO_ID}/motor/speed/"
56
+ rpm_data_topic = f"sdl-demo/picow/{PICO_ID}/motor/rpm/"
57
+
58
+ # random session id to keep track of the session and filter out old data
59
+ experiment_id = secrets.token_hex(4) # 4 bytes = 8 characters
60
+
61
+ rpm_data_queue = queue.Queue()
62
+
63
+
64
+ # Singleton: https://docs.streamlit.io/develop/api-reference/caching-and-state/st.cache_resource
65
+ @st.cache_resource
66
+ def create_paho_client(tls=True):
67
+ client = mqtt.Client(protocol=mqtt.MQTTv5)
68
+ if tls:
69
+ client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS_CLIENT)
70
+ return client
71
+
72
+
73
+ # Define setup separately since sensor_data is dynamic
74
+ def setup_paho_client(
75
+ client, rpm_data_topic, hostname, username, password=None, port=8883
76
+ ):
77
+ def on_message(client, userdata, msg):
78
+ rpm_data_queue.put(json.loads(msg.payload))
79
+
80
+ def on_connect(client, userdata, flags, rc, properties=None):
81
+ if rc != 0:
82
+ print("Connected with result code " + str(rc))
83
+ client.subscribe(rpm_data_topic, qos=1)
84
+
85
+ client.on_connect = on_connect
86
+ client.on_message = on_message
87
+
88
+ client.username_pw_set(username, password)
89
+ client.connect(hostname, port)
90
+ client.loop_start() # Use a non-blocking loop
91
+
92
+ return client
93
+
94
+
95
+ def send_command(client, command_topic, msg):
96
+ print("Sending command...")
97
+ result = client.publish(command_topic, json.dumps(msg), qos=2)
98
+ result.wait_for_publish() # Ensure the message is sent
99
+
100
+ if result.rc == mqtt.MQTT_ERR_SUCCESS:
101
+ print(f"Command sent: {msg} to topic {command_topic}")
102
+ else:
103
+ print(f"Failed to send command: {result.rc}")
104
+
105
+
106
+ # Helper function to plot RPM data
107
+ def plot_rpm_data(ax1, ax2, rpm_data):
108
+ times = [data["time"] for data in rpm_data]
109
+ rpm_values = [data["rpm"] for data in rpm_data]
110
+
111
+ ax1.clear()
112
+ ax1.plot(times, rpm_values, "-o", color="blue")
113
+ ax1.set_xlabel("Time (s)", fontsize=14)
114
+ ax1.set_ylabel("RPM", fontsize=14)
115
+ ax1.set_title("Motor RPM over Time", fontsize=16)
116
+
117
+ ax2.clear()
118
+ ax2.plot(times, rpm_values, "-o", color="blue")
119
+ ax2.set_ylim(0, max(1.1 * max(rpm_values), 1.1)) # Set fixed y-axis limits
120
+ ax2.set_xlabel("Time (s)")
121
+ ax2.set_ylabel("RPM (scaled)")
122
+ ax2.set_title("RPM Data Stream")
123
+
124
+ st.pyplot(fig)
125
+
126
+
127
+ # Function to check and update RPM data periodically
128
+ def check_rpm_data():
129
+ rpm_data = []
130
+ global fig, ax1, ax2
131
+ fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
132
+
133
+ start_time = time.time()
134
+ last_data_time = start_time
135
+ timeout = 15 # Timeout duration in seconds
136
+
137
+ rpm_display = st.empty()
138
+
139
+ while True:
140
+ current_time = time.time()
141
+ if not rpm_data_queue.empty():
142
+ data = rpm_data_queue.get()
143
+ elapsed_time = current_time - start_time
144
+ data["time"] = elapsed_time
145
+ rpm_data.append(data)
146
+ last_data_time = current_time
147
+
148
+ with rpm_display.container():
149
+ plot_rpm_data(ax1, ax2, rpm_data)
150
+ st.write("RPM Data Received:", data)
151
+
152
+ if current_time - last_data_time > timeout:
153
+ st.error(
154
+ f"No RPM data received for {timeout} seconds. Please check the system."
155
+ )
156
+ break
157
+
158
+ time.sleep(1)
159
+
160
+
161
+ # Publish button
162
+ if submit_button:
163
+ if not PICO_ID or not HIVEMQ_HOST or not HIVEMQ_USERNAME or not HIVEMQ_PASSWORD:
164
+ st.error("Please enter all required fields.")
165
+ else:
166
+ st.info(
167
+ f"Please wait while the command {speed} for experiment {experiment_id} is sent..."
168
+ )
169
+
170
+ client = create_paho_client(tls=True)
171
+
172
+ client = setup_paho_client(
173
+ client,
174
+ rpm_data_topic,
175
+ HIVEMQ_HOST,
176
+ HIVEMQ_USERNAME,
177
+ password=HIVEMQ_PASSWORD,
178
+ port=int(PORT),
179
+ )
180
+
181
+ command_msg = {"speed": speed, "_experiment_id": experiment_id}
182
+
183
+ send_command(client, command_topic, command_msg)
184
+ st.success(f"Command {speed} for experiment {experiment_id} sent successfully!")
185
+
186
+ # Start periodic check for RPM data
187
+ check_rpm_data()