gursi26 commited on
Commit
c5bd0e7
1 Parent(s): 2499126

added gradio code

Browse files
Files changed (2) hide show
  1. app.py +278 -3
  2. requirements.txt +52 -0
app.py CHANGED
@@ -1,7 +1,282 @@
1
  import gradio as gr
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
  demo.launch()
 
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 and client_state.value is not None:
189
+ credentials_changed = (
190
+ previous_credentials_state.value['username'] != HIVEMQ_USERNAME or
191
+ previous_credentials_state.value['password'] != HIVEMQ_PASSWORD or
192
+ previous_credentials_state.value['host'] != HIVEMQ_HOST or
193
+ previous_credentials_state.value['device_id'] != DEVICE_ID or
194
+ previous_credentials_state.value['port'] != PORT
195
+ )
196
+ if credentials_changed:
197
+ client_state.value.disconnect()
198
+ client_state.value = None
199
+
200
+ if client_state.value 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.value = client
219
+ response_queue_state.value = response_queue
220
+ previous_credentials_state.value = {
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.value
229
+ response_queue = response_queue_state.value
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()
requirements.txt CHANGED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ annotated-types==0.7.0
3
+ anyio==4.6.2.post1
4
+ certifi==2024.8.30
5
+ charset-normalizer==3.4.0
6
+ click==8.1.7
7
+ fastapi==0.115.3
8
+ ffmpy==0.4.0
9
+ filelock==3.16.1
10
+ fsspec==2024.10.0
11
+ gradio==5.4.0
12
+ gradio_client==1.4.2
13
+ h11==0.14.0
14
+ httpcore==1.0.6
15
+ httpx==0.27.2
16
+ huggingface-hub==0.26.1
17
+ idna==3.10
18
+ Jinja2==3.1.4
19
+ markdown-it-py==3.0.0
20
+ MarkupSafe==2.1.5
21
+ mdurl==0.1.2
22
+ numpy==2.1.2
23
+ orjson==3.10.10
24
+ packaging==24.1
25
+ paho-mqtt==2.1.0
26
+ pandas==2.2.3
27
+ pillow==11.0.0
28
+ pydantic==2.9.2
29
+ pydantic_core==2.23.4
30
+ pydub==0.25.1
31
+ Pygments==2.18.0
32
+ python-dateutil==2.9.0.post0
33
+ python-multipart==0.0.12
34
+ pytz==2024.2
35
+ PyYAML==6.0.2
36
+ requests==2.32.3
37
+ rich==13.9.3
38
+ ruff==0.7.1
39
+ safehttpx==0.1.1
40
+ semantic-version==2.10.0
41
+ shellingham==1.5.4
42
+ six==1.16.0
43
+ sniffio==1.3.1
44
+ starlette==0.41.0
45
+ tomlkit==0.12.0
46
+ tqdm==4.66.5
47
+ typer==0.12.5
48
+ typing_extensions==4.12.2
49
+ tzdata==2024.2
50
+ urllib3==2.2.3
51
+ uvicorn==0.32.0
52
+ websockets==12.0