from __future__ import annotations import logging from dataclasses import replace from pathlib import Path from PIL import Image from .matrix_driver import MatrixDriverOptions, get_default_driver_options logger = logging.getLogger(__name__) class MockDisplayDriver: name = "mock" hardware_mapping = "walnutpi-pi-bank-pwm-oe-v2" def __init__( self, data_dir: Path, brightness: int = 40, limit_refresh_rate_hz: int = 100, reason: str | None = None, driver_options: MatrixDriverOptions | None = None, ) -> None: self.data_dir = data_dir self.reason = reason self.available = reason is None self.last_frame_path = self.data_dir / "last_frame.png" self.brightness = brightness self.driver_options = driver_options or get_default_driver_options( brightness, limit_refresh_rate_hz, ) self.data_dir.mkdir(parents=True, exist_ok=True) if reason: logger.warning("Using mock display driver: %s", reason) else: logger.info("Using mock display driver") def set_image(self, image: Image.Image, *, synchronized: bool = False) -> None: image.save(self.last_frame_path) logger.debug("Saved mock frame to %s", self.last_frame_path) def clear(self) -> None: if self.last_frame_path.exists(): Image.new("RGB", (64, 64), (0, 0, 0)).save(self.last_frame_path) def set_brightness(self, value: int) -> None: self.brightness = value self.driver_options = replace(self.driver_options, brightness=value) def set_refresh_rate_limit(self, value: int) -> None: self.driver_options = replace( self.driver_options, limit_refresh_rate_hz=value, ) def close(self) -> None: self.clear() def get_status(self) -> dict: return { "driver": self.name, "driver_available": self.available, "driver_error": self.reason, "hardware_mapping": self.driver_options.hardware_mapping, "driver_options": self.driver_options.to_dict(), "driver_status": { "actual_refresh_rate_hz": None, "panel_scan_rate_hz": None, "completed_frames": None, "completed_scans": None, "scans_per_frame": None, "deadline_misses": None, "buffer_swaps": None, "submitted_frames": None, "oe_timing_backend": None, "oe_pulse_faults": None, "oe_forced_blanks": None, "max_programmed_oe_ns": None, "oe_timing_error": None, "safeoff_error": None, "cpu_affinity": None, "cpu_affinity_active": False, "cpu_affinity_error": None, "realtime_priority": None, "realtime_priority_active": False, "realtime_priority_error": None, "memory_locked": False, "memory_lock_error": None, "running": False, "governor": None, "last_error": self.reason, }, "last_frame": str(self.last_frame_path), }