2024-11-07 13:09:37 -04:00
|
|
|
from nicegui import run, ui
|
|
|
|
import subprocess
|
|
|
|
from loguru import logger
|
|
|
|
import os
|
|
|
|
|
|
|
|
GZ_TOPIC_INFO = ["gz", "topic", "-i", "-t"]
|
2024-11-14 13:46:50 -04:00
|
|
|
ENABLE_STREAMING_TOPIC = "/world/{world_name}/model/{robot_name}/link/pitch_link/sensor/camera/image/enable_streaming"
|
2024-11-07 13:09:37 -04:00
|
|
|
|
|
|
|
|
|
|
|
class EnableStreamingButton(ui.element):
|
2024-11-14 13:46:50 -04:00
|
|
|
def __init__(self, robot_name, state: bool = False) -> None:
|
2024-11-07 13:09:37 -04:00
|
|
|
super().__init__()
|
2024-11-14 13:46:50 -04:00
|
|
|
self.robot_name = robot_name
|
2024-11-07 13:09:37 -04:00
|
|
|
self._state = state
|
|
|
|
self.button = None
|
|
|
|
with self.classes():
|
|
|
|
with ui.row():
|
|
|
|
self.button = ui.button(on_click=self.on_click)
|
|
|
|
self.button._text = (
|
|
|
|
f'{"Disable" if self._state else "Enable"}' + " Video"
|
|
|
|
)
|
|
|
|
self.button.props(f'color={"red" if self._state else "green"}')
|
|
|
|
|
|
|
|
async def on_click(self) -> None:
|
|
|
|
spinner = ui.spinner(size="lg")
|
|
|
|
# So we don't block UI
|
2024-11-14 13:46:50 -04:00
|
|
|
result = await run.cpu_bound(self.enable_streaming, self.robot_name, not self._state)
|
2024-11-07 13:09:37 -04:00
|
|
|
if result:
|
|
|
|
ui.notify("Success", type="positive]")
|
2024-11-07 13:54:04 -04:00
|
|
|
self.set_state(state=not self._state)
|
2024-11-07 13:09:37 -04:00
|
|
|
else:
|
2024-11-07 13:54:04 -04:00
|
|
|
self.set_state(state=False)
|
2024-11-07 13:09:37 -04:00
|
|
|
ui.notify("No Video Streaming Available..", type="negative")
|
|
|
|
spinner.delete()
|
|
|
|
|
2024-11-07 13:54:04 -04:00
|
|
|
def set_state(self, state: bool):
|
|
|
|
self._state = state
|
|
|
|
self.update()
|
|
|
|
|
2024-11-07 13:09:37 -04:00
|
|
|
def update(self) -> None:
|
|
|
|
self.button._text = f'{"Disable" if self._state else "Enable"}' + " Video"
|
|
|
|
self.button.props(f'color={"red" if self._state else "green"}')
|
|
|
|
|
2024-11-07 13:54:04 -04:00
|
|
|
def stop_video(self):
|
|
|
|
if self._state != False:
|
2024-11-14 13:46:50 -04:00
|
|
|
self.enable_streaming(robot_name=self.robot_name, is_streaming=False)
|
2024-11-07 13:54:04 -04:00
|
|
|
self.set_state(state=False)
|
|
|
|
|
2024-11-07 13:09:37 -04:00
|
|
|
@staticmethod
|
2024-11-14 13:46:50 -04:00
|
|
|
def enable_streaming(robot_name: str, is_streaming: bool) -> bool:
|
2024-11-07 13:09:37 -04:00
|
|
|
|
|
|
|
world_name = os.environ["WORLD_NAME"]
|
|
|
|
# Check if this topic has any subscribers i.e. model is up
|
|
|
|
gz_topic_list_proc = subprocess.Popen(
|
|
|
|
GZ_TOPIC_INFO
|
2024-11-14 13:46:50 -04:00
|
|
|
+ [ENABLE_STREAMING_TOPIC.format(world_name=world_name, robot_name=robot_name)],
|
2024-11-07 13:09:37 -04:00
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
text=True,
|
|
|
|
)
|
|
|
|
# Check exceptions.. timeout, error etc.
|
|
|
|
|
|
|
|
output, error = gz_topic_list_proc.communicate(timeout=15)
|
|
|
|
if gz_topic_list_proc.returncode != 0:
|
|
|
|
logger.error(error)
|
|
|
|
return False
|
|
|
|
if "No subscribers".casefold() in output.casefold():
|
|
|
|
logger.error("No Subscribers on enable_streaming topic.")
|
|
|
|
return False
|
|
|
|
|
|
|
|
gz_topic_pub = [
|
|
|
|
"gz",
|
|
|
|
"topic",
|
|
|
|
"-t",
|
2024-11-14 13:46:50 -04:00
|
|
|
ENABLE_STREAMING_TOPIC.format(world_name=world_name, robot_name=robot_name),
|
2024-11-07 13:09:37 -04:00
|
|
|
"-m",
|
|
|
|
"gz.msgs.Boolean",
|
|
|
|
"-p",
|
|
|
|
f"data:{is_streaming}",
|
|
|
|
]
|
|
|
|
subprocess.run((gz_topic_pub))
|
|
|
|
return True
|