gursi26 commited on
Commit
2554ae8
1 Parent(s): fafda87

added logs

Browse files
Files changed (4) hide show
  1. .gitignore +1 -0
  2. app.py +5 -41
  3. client.py +170 -0
  4. utils.py +50 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
app.py CHANGED
@@ -1,45 +1,9 @@
1
  import streamlit as st
2
- import uuid
3
  import io, sys, time
 
4
 
5
- def get_user_id():
6
- if "user_id" not in st.session_state:
7
- query_params = st.query_params
8
- user_id = query_params.get("user_id", None)
9
- if not user_id:
10
- user_id = str(uuid.uuid4())
11
- st.query_params["user_id"] = user_id
12
- st.session_state.user_id = user_id
13
- return st.session_state.user_id
14
 
15
- user_id = get_user_id()
16
- st.write(f"Your unique ID is: {user_id}")
17
-
18
- # Capture stdout
19
- class StreamCapture(io.StringIO):
20
- def __init__(self):
21
- super().__init__()
22
- self.output = []
23
-
24
- def write(self, message):
25
- self.output.append(message)
26
- super().write(message)
27
-
28
- def get_output(self):
29
- return "".join(self.output)
30
-
31
- # Redirect stdout to capture
32
- capture = StreamCapture()
33
- sys.stdout = capture
34
-
35
- # Streamlit display section
36
- st.title("Live Output Stream")
37
- output_area = st.empty() # Placeholder for output display
38
-
39
- # Infinite loop to print a number every 10 seconds
40
- count = 1
41
- while True:
42
- print(f"Count: {count}")
43
- output_area.text(capture.get_output()) # Update Streamlit with captured output
44
- count += 1
45
- time.sleep(10)
 
1
  import streamlit as st
 
2
  import io, sys, time
3
+ from utils import *
4
 
5
+ render_log_window()
 
 
 
 
 
 
 
 
6
 
7
+ for i in range(10):
8
+ print(f"logger: {i}")
9
+ time.sleep(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
client.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
utils.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import uuid, io, sys
3
+
4
+ def get_user_id():
5
+ if "user_id" not in st.session_state:
6
+ query_params = st.query_params
7
+ user_id = query_params.get("user_id", None)
8
+ if not user_id:
9
+ user_id = str(uuid.uuid4())
10
+ st.query_params["user_id"] = user_id
11
+ st.session_state.user_id = user_id
12
+ return st.session_state.user_id
13
+
14
+ class StdoutRedirector(io.StringIO):
15
+ def __init__(self, log_area, max_lines=20):
16
+ super().__init__()
17
+ self.log_area = log_area
18
+ self.logs = []
19
+ self.max_lines = max_lines
20
+
21
+ def write(self, message):
22
+ if message.strip():
23
+ self.logs.append(message.strip())
24
+ if len(self.logs) > self.max_lines:
25
+ self.logs.pop(0)
26
+ self.log_area.markdown(
27
+ f"<div class='log-window'>{'<br>'.join(self.logs)}</div>",
28
+ unsafe_allow_html=True
29
+ )
30
+
31
+ def render_log_window():
32
+ st.markdown("""
33
+ <style>
34
+ .log-window {
35
+ height: 150px;
36
+ overflow-y: auto;
37
+ font-family: monospace;
38
+ background-color: var(--background-color);
39
+ color: var(--text-color);
40
+ padding: 10px;
41
+ border-radius: 5px;
42
+ border: 2px solid white;
43
+ }
44
+ </style>
45
+ """, unsafe_allow_html=True)
46
+
47
+ log_area = st.empty()
48
+ stdout_redirector = StdoutRedirector(log_area)
49
+
50
+ sys.stdout = stdout_redirector