# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import logging import os import re import subprocess try: import screeninfo except ImportError: screeninfo = None import RPi.GPIO as GPIO from vcgencmd import Vcgencmd from odoo.addons.hw_drivers.interface import Interface from odoo.addons.hw_drivers.tools import helpers _logger = logging.getLogger(__name__) MIN_IMAGE_VERSION_WAYLAND = 25.03 class DisplayInterface(Interface): _loop_delay = 3 connection_type = 'display' def get_devices(self): display_devices = {} dummy_display = { 'distant_display': { 'identifier': 'distant_display', 'name': 'Distant Display', } } if screeninfo is None: # On IoT image < 24.10 we don't have screeninfo installed, so we can't get the connected displays # We use old method to get the connected display hdmi_ports = {'hdmi_0': 2, 'hdmi_1': 7} if 'Pi 4' in GPIO.RPI_INFO.get('TYPE') else {'hdmi_0': 2} try: for x_screen, port in enumerate(hdmi_ports): if Vcgencmd().display_power_state(hdmi_ports.get(port)) == 'on': display_devices[port] = self._add_device(port, x_screen) except subprocess.CalledProcessError: _logger.warning('Vcgencmd "display_power_state" method call failed') return display_devices or dummy_display if float(helpers.get_version()[1:]) >= MIN_IMAGE_VERSION_WAYLAND: randr_result = subprocess.run(['wlr-randr'], capture_output=True, text=True) if randr_result.returncode != 0: return {} displays = re.findall(r"(?<=\()HDMI-A-\d(?=\))", randr_result.stdout) return { monitor: self._add_device(monitor, x_screen) for x_screen, monitor in enumerate(displays) } try: os.environ['DISPLAY'] = ':0' for x_screen, monitor in enumerate(screeninfo.get_monitors()): display_devices[monitor.name] = self._add_device(monitor.name, x_screen) return display_devices or dummy_display except screeninfo.common.ScreenInfoError: # If no display is connected, screeninfo raises an error, we return the distant display return dummy_display @classmethod def _add_device(cls, display_identifier, x_screen): """Creates a display_device dict. :param display_identifier: the identifier of the display :param x_screen: the x screen number :return: the display device dict """ return { 'identifier': display_identifier, 'name': 'Display - ' + display_identifier, 'x_screen': str(x_screen), }