feat(serial): add version test via 'ver()' command

- Add test_serial_version() to serial_monitor.py
- Sends 'ver()' command and parses version response
- Add 'Test Version' button in serial panel
- Displays version in status and log
This commit is contained in:
Jeremy Shen
2026-06-10 10:20:05 +08:00
parent fddcc3689a
commit 7ac04a6bea
2 changed files with 142 additions and 0 deletions
+93
View File
@@ -192,3 +192,96 @@ def read_serial_stream(
if line_callback:
line_callback(line)
return lines
def test_serial_version(
port: str,
baudrate: int = 115200,
timeout: float = 5.0,
) -> tuple[bool, str, str]:
"""Test serial port by sending 'ver()' command and parsing response.
Sends 'ver\\r\\n' to the serial port and reads the response.
Attempts to parse version string from the response.
Args:
port: Serial port device path (e.g., '/dev/ttyUSB0').
baudrate: Baud rate for serial communication.
timeout: Read timeout in seconds.
Returns:
Tuple of (success, message, version_string).
- (True, "Version: x.y.z", "x.y.z") — version detected
- (True, "Port responded", "") — port responded but no version
- (False, "Error message", "") — error occurred
"""
import serial
try:
with serial.Serial(port, baudrate, timeout=timeout) as ser:
# Clear buffers
ser.reset_input_buffer()
ser.reset_output_buffer()
# Send ver() command
ser.write(b"ver()\r\n")
# Read response
response = b""
start_time = __import__("time").time()
while __import__("time").time() - start_time < timeout:
if ser.in_waiting:
data = ser.read(ser.in_waiting)
response += data
# Check if we have a complete response
if b"\n" in data or b"\r" in data:
break
__import__("time").sleep(0.1)
# Decode response
response_str = response.decode("utf-8", errors="replace").strip()
if not response_str:
return False, "Port responded but no data received", ""
# Parse version from response
version = _parse_version_from_response(response_str)
if version:
return True, f"Version: {version}", version
else:
return True, f"Port responded: {response_str[:100]}", ""
except serial.SerialException as e:
return False, f"Serial error: {e}", ""
except Exception as e:
return False, f"Error: {e}", ""
def _parse_version_from_response(response: str) -> str:
"""Parse version string from serial response.
Args:
response: Response string from serial port.
Returns:
Version string if found, empty string otherwise.
"""
# Common version patterns
version_patterns = [
re.compile(r"([Vv]ersion[:\s]+)?([^\s;,\n]+v\d+\.\d+\.\d+[^\s;,\n]*)", re.IGNORECASE),
re.compile(r"(?:^|[\s:=])(v\d+\.\d+\.\d+)(?:\s|$)", re.IGNORECASE),
re.compile(r"(\d+\.\d+\.\d+)", re.IGNORECASE),
]
for pattern in version_patterns:
match = pattern.search(response)
if match:
# Return the version part (group 1 or group 2)
version = match.group(1) if match.lastindex and match.lastindex >= 1 else match.group(0)
# Clean up version string
version = version.strip().strip("';\"")
if version and len(version) > 2: # Basic validation
return version
return ""