gursi26 commited on
Commit
bd88e0f
1 Parent(s): 99baf46
Files changed (3) hide show
  1. .gitignore +2 -0
  2. app.py +79 -275
  3. utils.py +31 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__/
2
+ runner.py
app.py CHANGED
@@ -1,282 +1,86 @@
1
  import gradio as gr
2
- import paho.mqtt.client as mqtt
3
- import queue, json, base64, io, os
4
- from PIL import Image
5
 
6
- def create_paho_client(tls=True):
7
- client = mqtt.Client(client_id="", userdata=None, protocol=mqtt.MQTTv5)
8
- if tls:
9
- client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS_CLIENT)
10
- return client
11
 
12
- def setup_paho_client(client, username, password, cloud, port, device_id, response_queue):
13
- def on_message(client, userdata, msg):
14
- payload_dict = json.loads(msg.payload)
15
- response_queue.put(payload_dict)
16
-
17
- client.username_pw_set(username, password)
18
- client.connect(cloud, port)
19
- client.subscribe(device_id + "/response")
20
- client.on_message = on_message
21
- client.loop_start()
22
 
23
- def publish_and_wait(client, device_id, payload, response_queue):
24
- client.publish(device_id, payload=json.dumps(payload), qos=2)
25
- try:
26
- response = response_queue.get(block=True, timeout=10)
27
- except queue.Empty:
28
- response = None
29
- return response
30
 
31
- def handle_image_display(image):
32
- b64_bytes = base64.b64decode(image)
33
- img_bytes = io.BytesIO(b64_bytes)
34
- img = Image.open(img_bytes)
35
- return img
36
 
37
- with gr.Blocks() as demo:
38
- gr.Markdown("# MyCobot280 Pi Control Demo")
39
-
40
- gr.Markdown("""
41
- This app is a public demo of ...
42
- """)
43
-
44
- use_own_creds = gr.Checkbox(label="Use custom broker", value=False)
45
-
46
- # Placeholders for credentials inputs
47
- HIVEMQ_USERNAME = gr.Textbox(label="HIVEMQ Username", type="password", visible=False)
48
- HIVEMQ_PASSWORD = gr.Textbox(label="HIVEMQ Password", type="password", visible=False)
49
- HIVEMQ_HOST = gr.Textbox(label="HIVEMQ Host", visible=False)
50
- DEVICE_ID = gr.Textbox(label="Device ID", visible=False)
51
- PORT = gr.Number(label="Port", value=8883, visible=False)
52
-
53
- # Define function to update visibility of credential inputs
54
- def toggle_credentials(use_own_creds):
55
- visible = use_own_creds
56
- return {
57
- HIVEMQ_USERNAME: gr.update(visible=visible),
58
- HIVEMQ_PASSWORD: gr.update(visible=visible),
59
- HIVEMQ_HOST: gr.update(visible=visible),
60
- DEVICE_ID: gr.update(visible=visible),
61
- PORT: gr.update(visible=visible)
62
- }
63
-
64
- use_own_creds.change(fn=toggle_credentials, inputs=use_own_creds, outputs=[HIVEMQ_USERNAME, HIVEMQ_PASSWORD, HIVEMQ_HOST, DEVICE_ID, PORT])
65
-
66
- # Commands
67
- gr.Markdown("## Commands")
68
- commands = [
69
- "query/angles",
70
- "query/coords",
71
- "query/gripper",
72
- "query/camera",
73
- "control/angles",
74
- "control/coords",
75
- "control/gripper"
76
- ]
77
- selected_command = gr.Dropdown(choices=commands, label="Select command")
78
-
79
- # Placeholder for command arguments
80
- # We'll need to conditionally display inputs based on the selected command
81
-
82
- # Create a dictionary to store argument inputs for each command
83
- command_args = {}
84
- # For each command, define the inputs required
85
- with gr.Column(visible=False) as query_camera_args:
86
- quality = gr.Slider(label="Image quality", minimum=1, maximum=100, value=50)
87
- command_args["query/camera"] = [quality]
88
-
89
- # Similarly for other commands
90
- with gr.Column(visible=False) as control_angles_args:
91
- angle_1 = gr.Number(label="Angle 1", value=0.0)
92
- angle_2 = gr.Number(label="Angle 2", value=0.0)
93
- angle_3 = gr.Number(label="Angle 3", value=0.0)
94
- angle_4 = gr.Number(label="Angle 4", value=0.0)
95
- angle_5 = gr.Number(label="Angle 5", value=0.0)
96
- angle_6 = gr.Number(label="Angle 6", value=0.0)
97
- speed_angles = gr.Slider(label="Speed", minimum=1, maximum=100, value=50)
98
- command_args["control/angles"] = [angle_1, angle_2, angle_3, angle_4, angle_5, angle_6, speed_angles]
99
-
100
- with gr.Column(visible=False) as control_coords_args:
101
- x = gr.Number(label="x", value=0.0)
102
- y = gr.Number(label="y", value=0.0)
103
- z = gr.Number(label="z", value=0.0)
104
- rx = gr.Number(label="rx (Rotation x)", value=0.0)
105
- ry = gr.Number(label="ry (Rotation y)", value=0.0)
106
- rz = gr.Number(label="rz (Rotation z)", value=0.0)
107
- speed_coords = gr.Slider(label="Speed", minimum=1, maximum=100, value=50)
108
- command_args["control/coords"] = [x, y, z, rx, ry, rz, speed_coords]
109
-
110
- with gr.Column(visible=False) as control_gripper_args:
111
- gripper_value = gr.Slider(label="Gripper value", minimum=1, maximum=100, value=50)
112
- speed_gripper = gr.Slider(label="Speed", minimum=1, maximum=100, value=50)
113
- command_args["control/gripper"] = [gripper_value, speed_gripper]
114
-
115
- # Define function to update visibility of argument inputs based on selected command
116
- def update_args(selected_command):
117
- # First, set all arg groups to be hidden
118
- updates = {
119
- query_camera_args: gr.update(visible=False),
120
- control_angles_args: gr.update(visible=False),
121
- control_coords_args: gr.update(visible=False),
122
- control_gripper_args: gr.update(visible=False)
123
- }
124
- if selected_command == "query/camera":
125
- updates[query_camera_args] = gr.update(visible=True)
126
- elif selected_command == "control/angles":
127
- updates[control_angles_args] = gr.update(visible=True)
128
- elif selected_command == "control/coords":
129
- updates[control_coords_args] = gr.update(visible=True)
130
- elif selected_command == "control/gripper":
131
- updates[control_gripper_args] = gr.update(visible=True)
132
- return [updates[query_camera_args], updates[control_angles_args], updates[control_coords_args], updates[control_gripper_args]]
133
-
134
- selected_command.change(fn=update_args, inputs=selected_command, outputs=[query_camera_args, control_angles_args, control_coords_args, control_gripper_args])
135
-
136
- # Now, define a "Send Command" button
137
- send_command_button = gr.Button("Send Command")
138
-
139
- # Placeholder for displaying payload and response
140
- payload_display = gr.Markdown()
141
- response_display = gr.Markdown()
142
- image_display = gr.Image()
143
-
144
- # Define state variables
145
- client_state = gr.State(None)
146
- response_queue_state = gr.State(None)
147
- previous_credentials_state = gr.State({"username": None, "password": None, "host": None, "device_id": None, "port": None})
148
-
149
- # Define function to handle send command
150
- def send_command(use_own_creds, username, password, host, device_id, port, selected_command,
151
- quality, angle_1, angle_2, angle_3, angle_4, angle_5, angle_6, speed_angles,
152
- x, y, z, rx, ry, rz, speed_coords, gripper_value, speed_gripper,
153
- client_state, response_queue_state, previous_credentials_state):
154
- # Prepare args based on selected_command
155
- args = {}
156
- if selected_command == "query/angles":
157
- pass
158
- elif selected_command == "query/coords":
159
- pass
160
- elif selected_command == "query/gripper":
161
- pass
162
- elif selected_command == "query/camera":
163
- args = {"quality": quality}
164
- elif selected_command == "control/angles":
165
- args = {"angles": [angle_1, angle_2, angle_3, angle_4, angle_5, angle_6], "speed": speed_angles}
166
- elif selected_command == "control/coords":
167
- args = {"coords": [x, y, z, rx, ry, rz], "speed": speed_coords}
168
- elif selected_command == "control/gripper":
169
- args = {"gripper_value": gripper_value, "speed": speed_gripper}
170
- else:
171
- pass # Handle invalid command
172
-
173
- # Get credentials
174
- if use_own_creds:
175
- HIVEMQ_USERNAME = username
176
- HIVEMQ_PASSWORD = password
177
- HIVEMQ_HOST = host
178
- DEVICE_ID = device_id
179
- PORT = port
180
- else:
181
- HIVEMQ_USERNAME = os.environ.get("HIVEMQ_USERNAME")
182
- HIVEMQ_PASSWORD = os.environ.get("HIVEMQ_PASSWORD")
183
- HIVEMQ_HOST = os.environ.get("HIVEMQ_HOST")
184
- DEVICE_ID = os.environ.get("DEVICE_ID")
185
- PORT = int(os.environ.get("PORT", 8883))
186
-
187
- # Check if client is already connected and credentials haven't changed
188
- if client_state is not None:
189
- credentials_changed = (
190
- previous_credentials_state['username'] != HIVEMQ_USERNAME or
191
- previous_credentials_state['password'] != HIVEMQ_PASSWORD or
192
- previous_credentials_state['host'] != HIVEMQ_HOST or
193
- previous_credentials_state['device_id'] != DEVICE_ID or
194
- previous_credentials_state['port'] != PORT
195
- )
196
- if credentials_changed:
197
- client_state.disconnect()
198
- client_state = None
199
-
200
- if client_state is None:
201
- response_queue = queue.Queue()
202
- client = create_paho_client()
203
- try:
204
- setup_paho_client(
205
- client,
206
- HIVEMQ_USERNAME,
207
- HIVEMQ_PASSWORD,
208
- HIVEMQ_HOST,
209
- PORT,
210
- DEVICE_ID,
211
- response_queue
212
- )
213
- except Exception as e:
214
- payload_md = ""
215
- response_md = f"### Error\nFailed to connect to broker: {e}"
216
- return payload_md, response_md, None, client_state, response_queue_state, previous_credentials_state
217
-
218
- client_state = client
219
- response_queue_state = response_queue
220
- previous_credentials_state = {
221
- 'username': HIVEMQ_USERNAME,
222
- 'password': HIVEMQ_PASSWORD,
223
- 'host': HIVEMQ_HOST,
224
- 'device_id': DEVICE_ID,
225
- 'port': PORT
226
- }
227
- else:
228
- client = client_state
229
- response_queue = response_queue_state
230
-
231
- # Prepare payload
232
- payload = {"command": selected_command, "args": args}
233
- payload_md = f"### Payload\n```json\n{json.dumps(payload, indent=2)}\n```"
234
-
235
- # Publish and wait for response
236
- response = publish_and_wait(
237
- client,
238
- DEVICE_ID,
239
- payload,
240
- response_queue
241
- )
242
-
243
- # Prepare response display
244
- if response is not None:
245
- if "image" in response:
246
- image_b64 = response.pop("image")
247
- img = handle_image_display(image_b64)
248
- response_md = f"### Response\n```json\n{json.dumps(response, indent=2)}\n```"
249
- return payload_md, response_md, img, client_state, response_queue_state, previous_credentials_state
250
- else:
251
- response_md = f"### Response\n```json\n{json.dumps(response, indent=2)}\n```"
252
- return payload_md, response_md, None, client_state, response_queue_state, previous_credentials_state
253
- else:
254
- response_md = "### Response\nTimed out waiting for response. Is the on-device server running?"
255
- return payload_md, response_md, None, client_state, response_queue_state, previous_credentials_state
256
-
257
- # Now, set up the function to be called when the "Send Command" button is clicked
258
- send_command_button.click(
259
- fn=send_command,
260
- inputs=[
261
- use_own_creds,
262
- HIVEMQ_USERNAME,
263
- HIVEMQ_PASSWORD,
264
- HIVEMQ_HOST,
265
- DEVICE_ID,
266
- PORT,
267
- selected_command,
268
- quality,
269
- angle_1, angle_2, angle_3, angle_4, angle_5, angle_6, speed_angles,
270
- x, y, z, rx, ry, rz, speed_coords,
271
- gripper_value, speed_gripper,
272
- client_state, response_queue_state, previous_credentials_state
273
- ],
274
- outputs=[
275
- payload_display,
276
- response_display,
277
- image_display,
278
- client_state, response_queue_state, previous_credentials_state
279
- ]
280
- )
281
 
282
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import time
3
+ import random
 
4
 
5
+ def handle_request(selected_command, angle1=0.0, angle2=0.0, angle3=0.0, angle4=0.0, angle5=0.0, angle6=0.0,
6
+ coord1=0.0, coord2=0.0, coord3=0.0, coord4=0.0, coord5=0.0, coord6=0.0,
7
+ gripper_value=0.0, speed_angles=0.0, speed_coords=0.0, speed_gripper=0.0):
8
+ time.sleep(random.randint(1, 5))
9
+ return f"Command: {selected_command}, Params: {locals()}"
10
 
11
+ options = [
12
+ "query/angles", "query/coords", "query/camera", "query/gripper",
13
+ "control/angles", "control/coords", "control/gripper"
14
+ ]
 
 
 
 
 
 
15
 
16
+ with gr.Blocks() as app:
17
+ gr.Markdown("# MyCobot 280pi MQTT Control demo")
18
+ gr.Markdown("This is a public demo of the MyCobot 280pi...")
 
 
 
 
19
 
20
+ selected_command = gr.Dropdown(choices=options, label="Select command")
 
 
 
 
21
 
22
+ with gr.Group(visible=False) as query_angles_group:
23
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ with gr.Group(visible=False) as query_coords_group:
26
+ pass
27
+
28
+ with gr.Group(visible=False) as query_camera_group:
29
+ pass
30
+
31
+ with gr.Group(visible=False) as query_gripper_group:
32
+ pass
33
+
34
+ with gr.Group(visible=False) as control_angles_group:
35
+ angle1 = gr.Number(value=0.0, label="Angle 1", step=5.0)
36
+ angle2 = gr.Number(value=0.0, label="Angle 2", step=5.0)
37
+ angle3 = gr.Number(value=0.0, label="Angle 3", step=5.0)
38
+ angle4 = gr.Number(value=0.0, label="Angle 4", step=5.0)
39
+ angle5 = gr.Number(value=0.0, label="Angle 5", step=5.0)
40
+ angle6 = gr.Number(value=0.0, label="Angle 6", step=5.0)
41
+ speed_angles = gr.Slider(value=50.0, minimum=0.0, maximum=100.0, step=1.0, label="Speed")
42
+
43
+ with gr.Group(visible=False) as control_coords_group:
44
+ coord1 = gr.Number(value=0.0, label="X coordinate", step=5.0)
45
+ coord2 = gr.Number(value=0.0, label="Y coordinate", step=5.0)
46
+ coord3 = gr.Number(value=0.0, label="Z coordinate", step=5.0)
47
+ coord4 = gr.Number(value=0.0, label="Rotation X", step=5.0)
48
+ coord5 = gr.Number(value=0.0, label="Rotation Y", step=5.0)
49
+ coord6 = gr.Number(value=0.0, label="Rotation Z", step=5.0)
50
+ speed_coords = gr.Slider(value=50.0, minimum=0.0, maximum=100.0, step=1.0, label="Speed")
51
+
52
+ with gr.Group(visible=False) as control_gripper_group:
53
+ gripper_value = gr.Slider(minimum=0.0, maximum=100.0, step=1.0, label="Gripper value")
54
+ speed_gripper = gr.Slider(value=50.0, minimum=0.0, maximum=100.0, step=1.0, label="Speed")
55
+
56
+ def toggle_visibility(command):
57
+ return (
58
+ gr.update(visible=command == "query/angles"),
59
+ gr.update(visible=command == "query/coords"),
60
+ gr.update(visible=command == "query/camera"),
61
+ gr.update(visible=command == "query/gripper"),
62
+ gr.update(visible=command == "control/angles"),
63
+ gr.update(visible=command == "control/coords"),
64
+ gr.update(visible=command == "control/gripper")
65
+ )
66
+
67
+ selected_command.change(
68
+ toggle_visibility,
69
+ selected_command,
70
+ [
71
+ query_angles_group, query_coords_group, query_camera_group, query_gripper_group,
72
+ control_angles_group, control_coords_group, control_gripper_group
73
+ ]
74
+ )
75
+
76
+ submit_button = gr.Button("Send Command")
77
+ output_text = gr.Textbox()
78
+ submit_button.click(
79
+ handle_request,
80
+ inputs=[selected_command, angle1, angle2, angle3, angle4, angle5, angle6,
81
+ coord1, coord2, coord3, coord4, coord5, coord6, gripper_value, speed_angles,
82
+ speed_coords, speed_gripper],
83
+ outputs=output_text
84
+ )
85
+
86
+ app.launch(server_port=9000)
utils.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io, sys, os
2
+ import gradio as gr
3
+ import time
4
+ import sys
5
+ import io
6
+
7
+ def display_log_window():
8
+ def display_stdout():
9
+ while True:
10
+ yield stdout_buffer.getvalue()
11
+ time.sleep(1)
12
+
13
+ with gr.Blocks() as demo:
14
+ with gr.Row():
15
+ with gr.Column(visible=True) as sidebar:
16
+ output = gr.Textbox(interactive=False, lines=10, max_lines=20, show_label=False, elem_classes="log-window")
17
+ demo.load(display_stdout, outputs=output)
18
+
19
+ demo.queue().launch(server_port=9000)
20
+
21
+ stdout_buffer = io.StringIO()
22
+ sys.stdout = stdout_buffer
23
+
24
+
25
+ def get_credentials(use_own_creds: bool):
26
+ HIVEMQ_USERNAME = os.environ.get("HIVEMQ_USERNAME")
27
+ HIVEMQ_PASSWORD = os.environ.get("HIVEMQ_PASSWORD")
28
+ HIVEMQ_HOST = os.environ.get("HIVEMQ_HOST")
29
+ DEVICE_ENDPOINT = os.environ.get("DEVICE_ID")
30
+ PORT = int(os.environ.get("PORT", 8883))
31
+ return HIVEMQ_USERNAME, HIVEMQ_PASSWORD, HIVEMQ_HOST, DEVICE_ENDPOINT, PORT