Skip to content

Commit 142dd71

Browse files
committed
chore: add docstrings and reformat vnc_server
1 parent e8dc5f3 commit 142dd71

1 file changed

Lines changed: 81 additions & 8 deletions

File tree

manager/manager/vnc/vnc_server.py

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
"""VNC server management module for RoboticsApplicationManager.
2+
3+
Provides classes and functions to start and manage VNC and noVNC servers,
4+
including GPU-accelerated sessions and desktop icon creation.
5+
"""
6+
17
import time
28
import socket
39
from manager.manager.docker_thread.docker_thread import DockerThread
@@ -8,28 +14,49 @@
814

915

1016
class Vnc_server:
17+
"""Class to manage VNC and noVNC server sessions for RoboticsApplicationManager."""
18+
1119
threads: List[Any] = []
1220
running: bool = False
1321

1422
def start_vnc(self, display, internal_port, external_port):
23+
"""Start a VNC and noVNC server session.
24+
25+
Args:
26+
display (str): X display identifier.
27+
internal_port (int): Port for the VNC server.
28+
external_port (int): Port for the noVNC server.
29+
"""
1530
# Start X server in display
16-
xserver_cmd = f"/usr/bin/Xorg -quiet -noreset +extension GLX +extension RANDR +extension RENDER -logfile ./xdummy.log -config ./xorg.conf {display}"
31+
xserver_cmd = (
32+
f"/usr/bin/Xorg -quiet -noreset +extension GLX +extension RANDR "
33+
f"+extension RENDER -logfile ./xdummy.log -config ./xorg.conf {display}"
34+
)
1735
xserver_thread = DockerThread(xserver_cmd)
1836
xserver_thread.start()
1937
self.threads.append(xserver_thread)
2038
wait_for_xserver(display)
2139

2240
# Start VNC server without password, forever running in background
23-
x11vnc_cmd = f"x11vnc -repeat -quiet -display {display} -nopw -forever -xkb -bg -rfbport {internal_port}"
41+
x11vnc_cmd = (
42+
f"x11vnc -repeat -quiet -display {display} "
43+
f"-nopw -forever -xkb -bg -rfbport {internal_port}"
44+
)
2445
x11vnc_thread = DockerThread(x11vnc_cmd)
2546
x11vnc_thread.start()
2647
self.threads.append(x11vnc_thread)
2748

2849
# Start noVNC with default port 6080 listening to VNC server on 5900
2950
if self.get_ros_version() == "2":
30-
novnc_cmd = f"/noVNC/utils/novnc_proxy --listen {external_port} --vnc localhost:{internal_port}"
51+
novnc_cmd = (
52+
f"/noVNC/utils/novnc_proxy --listen {external_port} "
53+
f"--vnc localhost:{internal_port}"
54+
)
3155
else:
32-
novnc_cmd = f"/noVNC/utils/launch.sh --listen {external_port} --vnc localhost:{internal_port}"
56+
novnc_cmd = (
57+
f"/noVNC/utils/launch.sh --listen {external_port} "
58+
f"--vnc localhost:{internal_port}"
59+
)
3360

3461
novnc_thread = DockerThread(novnc_cmd)
3562
novnc_thread.start()
@@ -40,18 +67,38 @@ def start_vnc(self, display, internal_port, external_port):
4067
self.wait_for_port("localhost", external_port)
4168

4269
def start_vnc_gpu(self, display, internal_port, external_port, dri_path):
70+
"""Start a GPU-accelerated VNC and noVNC server session.
71+
72+
Args:
73+
display (str): X display identifier.
74+
internal_port (int): Port for the VNC server.
75+
external_port (int): Port for the noVNC server.
76+
dri_path (str): Path to the GPU device for hardware acceleration.
77+
"""
4378
# Start X and VNC servers
44-
turbovnc_cmd = f"export VGL_DISPLAY={dri_path} && export TVNC_WM=startlxde && /opt/TurboVNC/bin/vncserver {display} -geometry '1920x1080' -vgl -noreset -SecurityTypes None -rfbport {internal_port}"
79+
turbovnc_cmd = (
80+
f"export VGL_DISPLAY={dri_path} && "
81+
f"export TVNC_WM=startlxde && "
82+
f"/opt/TurboVNC/bin/vncserver {display} "
83+
f"-geometry '1920x1080' -vgl -noreset "
84+
f"-SecurityTypes None -rfbport {internal_port}"
85+
)
4586
turbovnc_thread = DockerThread(turbovnc_cmd)
4687
turbovnc_thread.start()
4788
self.threads.append(turbovnc_thread)
4889
wait_for_xserver(display)
4990

5091
# Start noVNC with default port 6080 listening to VNC server on 5900
5192
if self.get_ros_version() == "2":
52-
novnc_cmd = f"/noVNC/utils/novnc_proxy --listen {external_port} --vnc localhost:{internal_port}"
93+
novnc_cmd = (
94+
f"/noVNC/utils/novnc_proxy --listen {external_port} "
95+
f"--vnc localhost:{internal_port}"
96+
)
5397
else:
54-
novnc_cmd = f"/noVNC/utils/launch.sh --listen {external_port} --vnc localhost:{internal_port}"
98+
novnc_cmd = (
99+
f"/noVNC/utils/launch.sh --listen {external_port} "
100+
f"--vnc localhost:{internal_port}"
101+
)
55102

56103
novnc_thread = DockerThread(novnc_cmd)
57104
novnc_thread.start()
@@ -65,11 +112,24 @@ def start_vnc_gpu(self, display, internal_port, external_port, dri_path):
65112
self.create_gzclient_icon()
66113

67114
def wait_for_port(self, host, port, timeout=20):
115+
"""Wait for a TCP port on a host to become available within a timeout period.
116+
117+
Args:
118+
host (str): Hostname or IP address to check.
119+
port (int): Port number to check.
120+
timeout (int, optional): Maximum time to wait in seconds. Defaults to 20.
121+
122+
Raises:
123+
TimeoutError: If the port does not become available within the timeout.
124+
"""
68125
start_time = time.time()
69126
while True:
70127
if time.time() - start_time > timeout:
71128
raise TimeoutError(
72-
f"Port {port} on {host} didn't become available within {timeout} seconds."
129+
(
130+
f"Port {port} on {host} didn't become available "
131+
f"within {timeout} seconds."
132+
)
73133
)
74134
try:
75135
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
@@ -80,9 +140,15 @@ def wait_for_port(self, host, port, timeout=20):
80140
time.sleep(1)
81141

82142
def is_running(self):
143+
"""Check if the VNC server is currently running.
144+
145+
Returns:
146+
bool: True if running, False otherwise.
147+
"""
83148
return self.running
84149

85150
def terminate(self):
151+
"""Terminate all running threads and stop the VNC server."""
86152
for thread in self.threads:
87153
if thread.is_alive():
88154
thread.terminate()
@@ -91,10 +157,16 @@ def terminate(self):
91157
self.running = False
92158

93159
def get_ros_version(self):
160+
"""Get the current ROS version from the environment.
161+
162+
Returns:
163+
str: The ROS version as a string.
164+
"""
94165
output = subprocess.check_output(["bash", "-c", "echo $ROS_VERSION"])
95166
return output.decode("utf-8").strip()
96167

97168
def create_desktop_icon(self):
169+
"""Create a desktop icon to launch a terminal application."""
98170
try:
99171
desktop_dir = os.path.expanduser("~/Desktop")
100172
if not os.path.exists(desktop_dir):
@@ -116,6 +188,7 @@ def create_desktop_icon(self):
116188
print(err)
117189

118190
def create_gzclient_icon(self):
191+
"""Create a desktop icon to launch the Gazebo client application."""
119192
desktop_dir = os.path.expanduser("~/Desktop")
120193
if not os.path.exists(desktop_dir):
121194
os.makedirs(desktop_dir)

0 commit comments

Comments
 (0)