#!/usr/bin/env python3 """ MageDok Display Verifier Validates that the 7" display is running at 1024×600 resolution """ import os import re import subprocess import rclpy from rclpy.node import Node class DisplayVerifier(Node): def __init__(self): super().__init__('display_verifier') self.declare_parameter('target_width', 1024) self.declare_parameter('target_height', 600) self.declare_parameter('target_refresh', 60) self.target_w = self.get_parameter('target_width').value self.target_h = self.get_parameter('target_height').value self.target_f = self.get_parameter('target_refresh').value self.get_logger().info(f'Display Verifier: Target {self.target_w}×{self.target_h} @ {self.target_f}Hz') self.verify_display() def verify_display(self): """Check current display resolution via xdotool or xrandr""" try: # Try xrandr first result = subprocess.run(['xrandr'], capture_output=True, text=True, timeout=5) if result.returncode == 0: self.parse_xrandr(result.stdout) else: self.get_logger().warn('xrandr not available, checking edid-decode') self.check_edid() except Exception as e: self.get_logger().error(f'Display verification failed: {e}') def parse_xrandr(self, output): """Parse xrandr output to find active display resolution""" lines = output.split('\n') for line in lines: # Look for connected display with resolution if 'connected' in line and 'primary' in line: # Example: "HDMI-1 connected primary 1024x600+0+0 (normal left inverted right)" match = re.search(r'(\d+)x(\d+)', line) if match: width, height = int(match.group(1)), int(match.group(2)) self.verify_resolution(width, height) return self.get_logger().warn('Could not determine active display from xrandr') def verify_resolution(self, current_w, current_h): """Validate resolution matches target""" if current_w == self.target_w and current_h == self.target_h: self.get_logger().info(f'✓ Display verified: {current_w}×{current_h} [OK]') else: self.get_logger().warn(f'⚠ Display mismatch: Expected {self.target_w}×{self.target_h}, got {current_w}×{current_h}') self.attempt_set_resolution() def attempt_set_resolution(self): """Try to set resolution via xrandr""" try: # Find HDMI output result = subprocess.run( ['xrandr', '--output', 'HDMI-1', '--mode', f'{self.target_w}x{self.target_h}', '--rate', str(self.target_f)], capture_output=True, text=True, timeout=5 ) if result.returncode == 0: self.get_logger().info(f'✓ Resolution set to {self.target_w}×{self.target_h} @ {self.target_f}Hz') else: self.get_logger().warn(f'Resolution change failed: {result.stderr}') except Exception as e: self.get_logger().error(f'Could not set resolution: {e}') def check_edid(self): """Fallback: check EDID (Extended Display ID) data""" try: result = subprocess.run(['edid-decode', '/sys/class/drm/card0-HDMI-A-1/edid'], capture_output=True, text=True, timeout=5) if 'Established timings' in result.stdout: self.get_logger().info('Display EDID detected (MageDok 1024×600 display)') except: self.get_logger().warn('EDID check unavailable') def main(args=None): rclpy.init(args=args) verifier = DisplayVerifier() rclpy.shutdown() if __name__ == '__main__': main()