Spaces:
Sleeping
Sleeping
maybe
Browse files
app.py
CHANGED
|
@@ -5,45 +5,40 @@ from PIL import Image
|
|
| 5 |
|
| 6 |
@st.cache_resource
|
| 7 |
def create_paho_client(tls=True):
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
response = response_queue.get(block=True, timeout=10)
|
| 33 |
-
except queue.Empty:
|
| 34 |
-
response = None
|
| 35 |
-
return response
|
| 36 |
|
| 37 |
def handle_image_display(image):
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
|
| 43 |
st.title("MyCobot280 Pi control demo")
|
| 44 |
|
| 45 |
st.markdown("""
|
| 46 |
-
|
| 47 |
""")
|
| 48 |
|
| 49 |
use_own_creds = st.checkbox("Use your own credentials", value=False)
|
|
@@ -53,91 +48,122 @@ if use_own_creds:
|
|
| 53 |
HIVEMQ_PASSWORD = st.text_input("HIVEMQ Password", type="password")
|
| 54 |
HIVEMQ_HOST = st.text_input("HIVEMQ Host", type="password")
|
| 55 |
DEVICE_ID = st.text_input("Device ID", type="password")
|
| 56 |
-
PORT = st.number_input("Port", min_value=1, step=1)
|
| 57 |
else:
|
| 58 |
HIVEMQ_USERNAME = os.environ.get("HIVEMQ_USERNAME")
|
| 59 |
HIVEMQ_PASSWORD = os.environ.get("HIVEMQ_PASSWORD")
|
| 60 |
HIVEMQ_HOST = os.environ.get("HIVEMQ_HOST")
|
| 61 |
DEVICE_ID = os.environ.get("DEVICE_ID")
|
| 62 |
-
PORT = int(os.environ.get("PORT"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
st.markdown("## Commands")
|
| 65 |
commands = [
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
]
|
| 74 |
selected = st.selectbox("Select command: ", commands, key="selected_command", disabled=False)
|
| 75 |
|
| 76 |
args = {}
|
| 77 |
if st.session_state.selected_command == "query/angles":
|
| 78 |
-
|
| 79 |
elif st.session_state.selected_command == "query/coords":
|
| 80 |
-
|
| 81 |
elif st.session_state.selected_command == "query/gripper":
|
| 82 |
-
|
| 83 |
elif st.session_state.selected_command == "query/camera":
|
| 84 |
-
|
| 85 |
-
|
| 86 |
elif st.session_state.selected_command == "control/angles":
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
elif st.session_state.selected_command == "control/coords":
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
elif st.session_state.selected_command == "control/gripper":
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
|
| 117 |
with st.form("mqtt_form"):
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
handle_image_display(image)
|
| 140 |
-
else:
|
| 141 |
-
st.write(response)
|
| 142 |
-
else:
|
| 143 |
-
st.write("Timed out waiting for response. Is the on-device server running?")
|
|
|
|
| 5 |
|
| 6 |
@st.cache_resource
|
| 7 |
def create_paho_client(tls=True):
|
| 8 |
+
client = mqtt.Client(client_id="", userdata=None, protocol=mqtt.MQTTv5)
|
| 9 |
+
if tls:
|
| 10 |
+
client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS_CLIENT)
|
| 11 |
+
return client
|
| 12 |
+
|
| 13 |
+
def setup_paho_client(client, username, password, cloud, port, device_id, response_queue):
|
| 14 |
+
def on_message(client, userdata, msg):
|
| 15 |
+
payload_dict = json.loads(msg.payload)
|
| 16 |
+
response_queue.put(payload_dict)
|
| 17 |
+
|
| 18 |
+
client.username_pw_set(username, password)
|
| 19 |
+
client.connect(cloud, port)
|
| 20 |
+
client.subscribe(device_id + "/response")
|
| 21 |
+
client.on_message = on_message
|
| 22 |
+
client.loop_start()
|
| 23 |
+
|
| 24 |
+
def publish_and_wait(client, device_id, payload, response_queue):
|
| 25 |
+
client.publish(device_id, payload=json.dumps(payload), qos=2)
|
| 26 |
+
try:
|
| 27 |
+
response = response_queue.get(block=True, timeout=10)
|
| 28 |
+
except queue.Empty:
|
| 29 |
+
response = None
|
| 30 |
+
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
def handle_image_display(image):
|
| 33 |
+
b64_bytes = base64.b64decode(image)
|
| 34 |
+
img_bytes = io.BytesIO(b64_bytes)
|
| 35 |
+
img = Image.open(img_bytes)
|
| 36 |
+
st.image(img, caption="Cobot camera view")
|
| 37 |
|
| 38 |
st.title("MyCobot280 Pi control demo")
|
| 39 |
|
| 40 |
st.markdown("""
|
| 41 |
+
This app is a public demo of ...
|
| 42 |
""")
|
| 43 |
|
| 44 |
use_own_creds = st.checkbox("Use your own credentials", value=False)
|
|
|
|
| 48 |
HIVEMQ_PASSWORD = st.text_input("HIVEMQ Password", type="password")
|
| 49 |
HIVEMQ_HOST = st.text_input("HIVEMQ Host", type="password")
|
| 50 |
DEVICE_ID = st.text_input("Device ID", type="password")
|
| 51 |
+
PORT = st.number_input("Port", min_value=1, step=1, value=8883)
|
| 52 |
else:
|
| 53 |
HIVEMQ_USERNAME = os.environ.get("HIVEMQ_USERNAME")
|
| 54 |
HIVEMQ_PASSWORD = os.environ.get("HIVEMQ_PASSWORD")
|
| 55 |
HIVEMQ_HOST = os.environ.get("HIVEMQ_HOST")
|
| 56 |
DEVICE_ID = os.environ.get("DEVICE_ID")
|
| 57 |
+
PORT = int(os.environ.get("PORT", 8883))
|
| 58 |
+
|
| 59 |
+
# Initialize or update the MQTT client and response queue in session state
|
| 60 |
+
if 'client' not in st.session_state:
|
| 61 |
+
st.session_state['client'] = None
|
| 62 |
+
st.session_state['response_queue'] = None
|
| 63 |
+
st.session_state['HIVEMQ_USERNAME'] = None
|
| 64 |
+
st.session_state['HIVEMQ_PASSWORD'] = None
|
| 65 |
+
st.session_state['HIVEMQ_HOST'] = None
|
| 66 |
+
st.session_state['DEVICE_ID'] = None
|
| 67 |
+
st.session_state['PORT'] = None
|
| 68 |
+
|
| 69 |
+
credentials_changed = (
|
| 70 |
+
st.session_state['HIVEMQ_USERNAME'] != HIVEMQ_USERNAME or
|
| 71 |
+
st.session_state['HIVEMQ_PASSWORD'] != HIVEMQ_PASSWORD or
|
| 72 |
+
st.session_state['HIVEMQ_HOST'] != HIVEMQ_HOST or
|
| 73 |
+
st.session_state['DEVICE_ID'] != DEVICE_ID or
|
| 74 |
+
st.session_state['PORT'] != PORT
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
if st.session_state['client'] is None or credentials_changed:
|
| 78 |
+
st.session_state['HIVEMQ_USERNAME'] = HIVEMQ_USERNAME
|
| 79 |
+
st.session_state['HIVEMQ_PASSWORD'] = HIVEMQ_PASSWORD
|
| 80 |
+
st.session_state['HIVEMQ_HOST'] = HIVEMQ_HOST
|
| 81 |
+
st.session_state['DEVICE_ID'] = DEVICE_ID
|
| 82 |
+
st.session_state['PORT'] = PORT
|
| 83 |
+
st.session_state['response_queue'] = queue.Queue()
|
| 84 |
+
st.session_state['client'] = create_paho_client()
|
| 85 |
+
setup_paho_client(
|
| 86 |
+
st.session_state['client'],
|
| 87 |
+
HIVEMQ_USERNAME,
|
| 88 |
+
HIVEMQ_PASSWORD,
|
| 89 |
+
HIVEMQ_HOST,
|
| 90 |
+
PORT,
|
| 91 |
+
DEVICE_ID,
|
| 92 |
+
st.session_state['response_queue']
|
| 93 |
+
)
|
| 94 |
|
| 95 |
st.markdown("## Commands")
|
| 96 |
commands = [
|
| 97 |
+
"query/angles",
|
| 98 |
+
"query/coords",
|
| 99 |
+
"query/gripper",
|
| 100 |
+
"query/camera",
|
| 101 |
+
"control/angles",
|
| 102 |
+
"control/coords",
|
| 103 |
+
"control/gripper"
|
| 104 |
]
|
| 105 |
selected = st.selectbox("Select command: ", commands, key="selected_command", disabled=False)
|
| 106 |
|
| 107 |
args = {}
|
| 108 |
if st.session_state.selected_command == "query/angles":
|
| 109 |
+
pass
|
| 110 |
elif st.session_state.selected_command == "query/coords":
|
| 111 |
+
pass
|
| 112 |
elif st.session_state.selected_command == "query/gripper":
|
| 113 |
+
pass
|
| 114 |
elif st.session_state.selected_command == "query/camera":
|
| 115 |
+
quality = st.slider("Image quality", 1, 100, 50)
|
| 116 |
+
args = {"quality": quality}
|
| 117 |
elif st.session_state.selected_command == "control/angles":
|
| 118 |
+
col1, col2, col3 = st.columns(3)
|
| 119 |
+
with col1:
|
| 120 |
+
angle_1 = st.number_input("Angle 1", format="%.2f")
|
| 121 |
+
angle_4 = st.number_input("Angle 4", format="%.2f")
|
| 122 |
+
with col2:
|
| 123 |
+
angle_2 = st.number_input("Angle 2", format="%.2f")
|
| 124 |
+
angle_5 = st.number_input("Angle 5", format="%.2f")
|
| 125 |
+
with col3:
|
| 126 |
+
angle_3 = st.number_input("Angle 3", format="%.2f")
|
| 127 |
+
angle_6 = st.number_input("Angle 6", format="%.2f")
|
| 128 |
+
speed = st.slider("Speed", 1, 100, 50)
|
| 129 |
+
args = {"angles": [angle_1, angle_2, angle_3, angle_4, angle_5, angle_6], "speed": speed}
|
| 130 |
elif st.session_state.selected_command == "control/coords":
|
| 131 |
+
col1, col2, col3 = st.columns(3)
|
| 132 |
+
with col1:
|
| 133 |
+
x = st.number_input("x", format="%.2f")
|
| 134 |
+
rx = st.number_input("rx (Rotation x)", format="%.2f")
|
| 135 |
+
with col2:
|
| 136 |
+
y = st.number_input("y", format="%.2f")
|
| 137 |
+
ry = st.number_input("ry (Rotation y)", format="%.2f")
|
| 138 |
+
with col3:
|
| 139 |
+
z = st.number_input("z", format="%.2f")
|
| 140 |
+
rz = st.number_input("rz (Rotation z)", format="%.2f")
|
| 141 |
+
speed = st.slider("Speed", 1, 100, 50)
|
| 142 |
+
args = {"coords": [x, y, z, rx, ry, rz], "speed": speed}
|
| 143 |
elif st.session_state.selected_command == "control/gripper":
|
| 144 |
+
gripper_value = st.slider("Gripper value", 1, 100, 50)
|
| 145 |
+
speed = st.slider("Speed", 1, 100, 50)
|
| 146 |
+
args = {"gripper_value": gripper_value, "speed": speed}
|
| 147 |
|
| 148 |
with st.form("mqtt_form"):
|
| 149 |
+
if st.form_submit_button("Send Command"):
|
| 150 |
+
payload = {"command": st.session_state.selected_command, "args": args}
|
| 151 |
+
st.markdown("### Payload")
|
| 152 |
+
st.write(payload)
|
| 153 |
+
|
| 154 |
+
response = publish_and_wait(
|
| 155 |
+
st.session_state['client'],
|
| 156 |
+
DEVICE_ID,
|
| 157 |
+
payload,
|
| 158 |
+
st.session_state['response_queue']
|
| 159 |
+
)
|
| 160 |
+
st.markdown("### Response")
|
| 161 |
+
if response is not None:
|
| 162 |
+
if "image" in response:
|
| 163 |
+
image = response.pop("image")
|
| 164 |
+
st.write(response)
|
| 165 |
+
handle_image_display(image)
|
| 166 |
+
else:
|
| 167 |
+
st.write(response)
|
| 168 |
+
else:
|
| 169 |
+
st.write("Timed out waiting for response. Is the on-device server running?")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|