gursi26 commited on
Commit
7e745ee
1 Parent(s): b498103

added client and connected functions

Browse files
Files changed (2) hide show
  1. app.py +55 -13
  2. client.py +181 -0
app.py CHANGED
@@ -1,15 +1,52 @@
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
 
@@ -61,26 +98,31 @@ with gr.Blocks() as app:
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()
 
1
  import gradio as gr
2
+ from PIL import Image
3
+ from client import CobotController
4
+ from utils import get_credentials
5
+ import json
6
+ import uuid
7
 
8
+ user, pwd, host, endpoint, port = get_credentials(False)
9
+ client = CobotController(user, pwd, host, port, endpoint)
10
+
11
+ def handle_request(
12
+ selected_command, angle1=0.0, angle2=0.0, angle3=0.0, angle4=0.0,
13
+ angle5=0.0, angle6=0.0, coord1=0.0, coord2=0.0, coord3=0.0, coord4=0.0,
14
+ coord5=0.0, coord6=0.0, gripper_value=0.0, speed_angles=0.0, speed_coords=0.0,
15
+ speed_gripper=0.0
16
+ ):
17
+ img = None
18
+ if selected_command == "query/angles":
19
+ response = client.get_angles()
20
+ elif selected_command == "query/coords":
21
+ response = client.get_coords()
22
+ elif selected_command == "query/gripper":
23
+ response = client.get_gripper_value()
24
+ elif selected_command == "query/camera":
25
+ response = client.get_camera()
26
+ img = response.pop("image")
27
+ elif selected_command == "control/angles":
28
+ response = client.send_angles(
29
+ angle_list = [angle1, angle2, angle3, angle4, angle5, angle6],
30
+ speed = speed_angles
31
+ )
32
+ elif selected_command == "control/coords":
33
+ response = client.send_coords(
34
+ angle_list = [coord1, coord2, coord3, coord4, coord5, coord6],
35
+ speed = speed_coords
36
+ )
37
+ elif selected_command == "control/gripper":
38
+ response = client.send_gripper_value(
39
+ value = gripper_value,
40
+ speed = speed_gripper
41
+ )
42
+
43
+ text_output = json.dumps(response, indent=4)
44
+ if img is not None:
45
+ return text_output, gr.update(value=img, visible=True)
46
+ return text_output, None
47
 
48
  options = [
49
+ "query/angles", "query/coords", "query/gripper", "query/camera",
50
  "control/angles", "control/coords", "control/gripper"
51
  ]
52
 
 
98
  gr.update(visible=command == "query/gripper"),
99
  gr.update(visible=command == "control/angles"),
100
  gr.update(visible=command == "control/coords"),
101
+ gr.update(visible=command == "control/gripper"),
102
+ gr.update(visible=False),
103
+ gr.update(value="")
104
  )
105
 
106
+ submit_button = gr.Button("Send Command")
107
+ output_text = gr.Textbox(label="")
108
+ output_image = gr.Image(visible=False)
109
+
110
  selected_command.change(
111
  toggle_visibility,
112
  selected_command,
113
  [
114
  query_angles_group, query_coords_group, query_camera_group, query_gripper_group,
115
+ control_angles_group, control_coords_group, control_gripper_group, output_image,
116
+ output_text
117
  ]
118
  )
119
 
 
 
120
  submit_button.click(
121
  handle_request,
122
  inputs=[selected_command, angle1, angle2, angle3, angle4, angle5, angle6,
123
  coord1, coord2, coord3, coord4, coord5, coord6, gripper_value, speed_angles,
124
  speed_coords, speed_gripper],
125
+ outputs=[output_text, output_image]
126
  )
127
 
128
  app.launch()
client.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # installed packages
2
+ from PIL import Image
3
+ import paho.mqtt.client as paho
4
+
5
+ # base python packages
6
+ import json, io, base64
7
+ from queue import Queue
8
+ from datetime import datetime
9
+ import uuid
10
+
11
+ def print_with_timestamp(message):
12
+ print(f"[{datetime.now().strftime('%b %d, %H:%M:%S')}] {message}")
13
+
14
+ class CobotController:
15
+ user_id = str(uuid.uuid4())
16
+
17
+ def __init__(
18
+ self,
19
+ hive_mq_username: str,
20
+ hive_mq_password: str,
21
+ hive_mq_cloud: str,
22
+ port: int,
23
+ device_endpoint: str,
24
+ user_id: str = None
25
+ ):
26
+ # setup client and response queues
27
+ self.client = paho.Client(client_id="", userdata=None, protocol=paho.MQTTv5)
28
+ self.client.tls_set()
29
+ self.client.username_pw_set(hive_mq_username, hive_mq_password)
30
+ self.client.connect(hive_mq_cloud, port)
31
+
32
+ self.response_queue = Queue()
33
+ def on_message(client, userdata, msg):
34
+ payload_dict = json.loads(msg.payload)
35
+ self.response_queue.put(payload_dict)
36
+
37
+ def on_connect(client, userdata, flags, rc, properties=None):
38
+ print_with_timestamp("Connected to HiveMQ broker...")
39
+
40
+ self.client.on_connect = on_connect
41
+ self.client.on_message = on_message
42
+ self.client.loop_start()
43
+
44
+ # initialize user id and endpoints
45
+ if user_id is not None:
46
+ CobotController.user_id = user_id
47
+ self.user_id = CobotController.user_id
48
+
49
+ self.device_endpoint = device_endpoint
50
+ self.init_endpoint = self.device_endpoint + "/init"
51
+ self.publish_endpoint = self.device_endpoint + "/" + self.user_id
52
+ self.incoming_endpoint = self.publish_endpoint + "/response"
53
+ self.client.subscribe(self.incoming_endpoint, qos=2)
54
+
55
+ connected = self.check_connection_status()
56
+ if connected:
57
+ return
58
+
59
+ # send an init request
60
+ print_with_timestamp("Sending a connection request...")
61
+ pub_handle = self.client.publish(
62
+ self.init_endpoint,
63
+ payload=json.dumps({"id": self.user_id}),
64
+ qos=2
65
+ )
66
+ pub_handle.wait_for_publish()
67
+
68
+ # get a response for the init message, if no response, have to wait for current users time to end
69
+ print_with_timestamp("Waiting for cobot access...")
70
+ prev_pos = None
71
+ while True:
72
+ try:
73
+ payload = self.response_queue.get(timeout=10)
74
+ if payload["status"] == "ready":
75
+ self.client.publish(
76
+ self.publish_endpoint,
77
+ payload=json.dumps({"yeehaw": []}),
78
+ qos=2
79
+ )
80
+ print_with_timestamp("Connected to server successfully.")
81
+ break
82
+
83
+ except Exception as e:
84
+ resp = self.handle_publish_and_response(
85
+ payload=json.dumps({"id": self.user_id}),
86
+ custom_endpoint=self.device_endpoint + "/queuequery"
87
+ )
88
+ if "queue_pos" not in resp:
89
+ break
90
+ pos = resp["queue_pos"]
91
+ if prev_pos == None:
92
+ prev_pos = pos
93
+ elif prev_pos == pos:
94
+ continue
95
+ prev_pos = pos
96
+ print_with_timestamp(f"Waiting for cobot access. There are {pos - 1} users ahead of you...")
97
+
98
+ def check_connection_status(self):
99
+ self.client.publish(
100
+ self.publish_endpoint,
101
+ payload=json.dumps({"command":"query/angles", "args": {}}),
102
+ qos=2
103
+ )
104
+ try: # if we recieve any response, it means the server is currently servicing our requests
105
+ _ = self.response_queue.get(timeout=5)
106
+ return True
107
+ except Exception as _:
108
+ return False
109
+
110
+ def handle_publish_and_response(self, payload, custom_endpoint=None):
111
+ if custom_endpoint is None:
112
+ self.client.publish(self.publish_endpoint, payload=payload, qos=2)
113
+ else:
114
+ self.client.publish(custom_endpoint, payload=payload, qos=2)
115
+ return self.response_queue.get(block=True)
116
+
117
+ def send_angles(
118
+ self,
119
+ angle_list: list[float] = [0.0] * 6,
120
+ speed: int = 50
121
+ ):
122
+ payload = json.dumps({"command": "control/angles",
123
+ "args": {"angles": angle_list, "speed": speed}})
124
+ return self.handle_publish_and_response(payload)
125
+
126
+ def send_coords(
127
+ self,
128
+ coord_list: list[float] = [0.0] * 6,
129
+ speed: int = 50
130
+ ):
131
+ payload = json.dumps({"command": "control/coords",
132
+ "args": {"coords": coord_list, "speed": speed}})
133
+ return self.handle_publish_and_response(payload)
134
+
135
+ def send_gripper_value(
136
+ self,
137
+ value: int = 100,
138
+ speed: int = 50
139
+ ):
140
+ payload = json.dumps({"command": "control/gripper",
141
+ "args": {"gripper_value": value, "speed": speed}})
142
+ return self.handle_publish_and_response(payload)
143
+
144
+ def get_angles(self):
145
+ payload = json.dumps({"command": "query/angles", "args": {}})
146
+ return self.handle_publish_and_response(payload)
147
+
148
+ def get_coords(self):
149
+ payload = json.dumps({"command": "query/coords", "args": {}})
150
+ return self.handle_publish_and_response(payload)
151
+
152
+ def get_gripper_value(self):
153
+ payload = json.dumps({"command": "query/gripper", "args": {}})
154
+ return self.handle_publish_and_response(payload)
155
+
156
+ def get_camera(self, quality=100, save_path=None):
157
+ payload = json.dumps({"command": "query/camera", "args": {"quality": quality}})
158
+ response = self.handle_publish_and_response(payload)
159
+ if not response["success"]:
160
+ return response
161
+
162
+ b64_bytes = base64.b64decode(response["image"])
163
+ img_bytes = io.BytesIO(b64_bytes)
164
+ img = Image.open(img_bytes)
165
+
166
+ response["image"] = img
167
+ if save_path is not None:
168
+ img.save(save_path)
169
+
170
+ return response
171
+
172
+ if __name__ == "__main__":
173
+ from my_secrets import *
174
+
175
+ cobot = CobotController(
176
+ HIVEMQ_USERNAME,
177
+ HIVEMQ_PASSWORD,
178
+ HIVEMQ_HOST,
179
+ DEVICE_PORT,
180
+ DEVICE_ENDPOINT,
181
+ )