Skip to content

Commit 93c2b68

Browse files
committed
Improve mavsdk_server logging integration
- Parse mavsdk_server log levels (Debug/Info/Warn/Error) and map to Python logging - Strip ANSI color codes from server output - Use 'mavsdk_server' as logger name - Make warning/error messages visible by default, INFO/DEBUG not
1 parent 7b138bd commit 93c2b68

File tree

1 file changed

+58
-7
lines changed

1 file changed

+58
-7
lines changed

mavsdk/system.py

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,64 @@
5151

5252

5353
class _LoggingThread(threading.Thread):
54-
def __init__(self, pipe, log_fn):
54+
def __init__(self, pipe, logger):
5555
super().__init__()
5656
self.pipe = pipe
57-
self.log_fn = log_fn
57+
self.logger = logger
5858

5959
def run(self):
60-
for line in self.pipe:
61-
self.log_fn(line.decode("utf-8").replace("\n", ""))
60+
try:
61+
for line in self.pipe:
62+
if not line: # EOF reached
63+
break
64+
65+
try:
66+
message = line.decode("utf-8").replace("\n", "")
67+
68+
# Skip empty lines
69+
if not message.strip():
70+
continue
71+
72+
# Strip ANSI color codes used by MAVSDK
73+
# MAVSDK uses: \x1b[31m, \x1b[32m, \x1b[33m, \x1b[34m, \x1b[37m, \x1b[0m
74+
# Also handle \033[ variant (equivalent to \x1b[)
75+
for escape_seq in ['\x1b[', '\033[']:
76+
while escape_seq in message:
77+
start = message.find(escape_seq)
78+
if start == -1:
79+
break
80+
end = message.find('m', start)
81+
if end == -1:
82+
break
83+
message = message[:start] + message[end + 1:]
84+
85+
# Parse mavsdk_server log level prefixes and map to Python logging levels
86+
# Format is: [timestamp|Level] message (filename:line)
87+
if "|Error] " in message:
88+
idx = message.find("|Error] ") + 8
89+
self.logger.error(message[idx:].strip())
90+
elif "|Warn ] " in message:
91+
idx = message.find("|Warn ] ") + 8
92+
self.logger.warning(message[idx:].strip())
93+
elif "|Info ] " in message:
94+
idx = message.find("|Info ] ") + 8
95+
self.logger.info(message[idx:].strip())
96+
elif "|Debug] " in message:
97+
idx = message.find("|Debug] ") + 8
98+
self.logger.debug(message[idx:].strip())
99+
else:
100+
# Default to debug for unprefixed messages
101+
self.logger.debug(message)
102+
except UnicodeDecodeError:
103+
# Skip lines that can't be decoded
104+
continue
105+
except (BrokenPipeError, OSError):
106+
# Subprocess has terminated, exit gracefully
107+
pass
108+
finally:
109+
# Ensure pipe is closed
110+
if self.pipe and not self.pipe.closed:
111+
self.pipe.close()
62112

63113
class System:
64114
"""
@@ -120,7 +170,7 @@ async def connect(self, system_address=None):
120170

121171
# add a delay to be sure resources have been freed and restart mavsdk_server
122172
await asyncio.sleep(1)
123-
173+
124174

125175
if self._mavsdk_server_address is None:
126176
self._mavsdk_server_address = 'localhost'
@@ -456,13 +506,14 @@ def _start_mavsdk_server(system_address, port, sysid, compid):
456506
"--compid", str(compid)]
457507
if system_address:
458508
bin_path_and_args.append(system_address)
509+
459510
p = subprocess.Popen(bin_path_and_args,
460511
shell=False,
461512
stdout=subprocess.PIPE,
462513
stderr=subprocess.STDOUT)
463514

464-
logger = logging.getLogger(__name__)
465-
log_thread = _LoggingThread(p.stdout, logger.debug)
515+
logger = logging.getLogger('mavsdk_server')
516+
log_thread = _LoggingThread(p.stdout, logger)
466517
log_thread.start()
467518
except FileNotFoundError:
468519
print("""

0 commit comments

Comments
 (0)