From cc7a973c9ac5cf3d2fa8a559ffd9ed18d01b106e Mon Sep 17 00:00:00 2001 From: Hendrik Sokolowski Date: Wed, 10 Apr 2024 22:04:01 +0200 Subject: [PATCH] switch off display via xorg.xset --- flake.nix | 6 ++++-- src/display.py | 40 +++++++++++++++++++++++++++++++++++----- src/ha-kiosk-agent | 7 ++++--- src/sensor.py | 19 ++++++------------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/flake.nix b/flake.nix index b9ef44f..66b87d2 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,8 @@ version = "0.0.1"; src = ./src; propagatedBuildInputs = with pkgs.python311Packages; [ - pkgs.brightnessctl + pkgs.light + pkgs.xorg.xset coloredlogs configargparse @@ -26,7 +27,8 @@ devShells.default = pkgs.mkShell { name = "development shell"; nativeBuildInputs = with pkgs.python311Packages; [ - pkgs.brightnessctl + pkgs.light + pkgs.xorg.xset coloredlogs configargparse diff --git a/src/display.py b/src/display.py index 73d2b61..04ebb54 100644 --- a/src/display.py +++ b/src/display.py @@ -24,11 +24,14 @@ class DisplayBrightnessManager(): brightness_level = BrightnessLevel.LEVEL_BRIGHT mqtt_entity = None + display_device = None + display_switched_off = False touch_device = None logger = None - def __init__(self, device, touch_device, logger: logging.Logger): + def __init__(self, device, display_device, touch_device, logger: logging.Logger): self.logger = logger + self.display_device = display_device self.touch_device = self.get_touch_device(touch_device) force_display_on_info = ha_mqtt_discoverable.sensors.SwitchInfo( @@ -74,6 +77,17 @@ class DisplayBrightnessManager(): self.brightness_mode_new = mode logging.info(f'brightness mode: {self.brightness_mode}, new mode: {self.brightness_mode_new}') + async def switch_display_on(self): + self.logger.info('switching screen on') + self.display_switched_off = False + await asyncio.create_subprocess_exec('xset', '-display', self.display_device, 'dpms', 'force', 'on') + + async def switch_display_off(self): + self.logger.info('switching screen off') + self.display_switched_off = True + await asyncio.create_subprocess_exec('xset', '-display', self.display_device, 's', 'activate') + + async def input_device_loop(self): async for ev in self.touch_device.async_read_loop(): now = time.time() @@ -89,17 +103,32 @@ class DisplayBrightnessManager(): elif self.brightness_level == BrightnessLevel.LEVEL_BRIGHT: from_value = 50 - step_val=(to_value-from_value)/25 - for i in range(1, 25): + if to_value != 0 and self.display_switched_off: + self.logger.info(f'setting initial brightness to {to_value:.0f}%') + await asyncio.create_subprocess_exec('light', '-S', f'{to_value:.0f}%', stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL) + await asyncio.sleep(0.01) + await self.switch_display_on() + return + + self.logger.info(f'dimming screen from {from_value} to {to_value}') + step_val=(to_value-from_value)/20 + last_val = from_value + for i in range(1, 20): new_val = "{:.0f}".format(from_value + i*step_val) - await asyncio.create_subprocess_exec('brightnessctl', 'set', f'{new_val}%', stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL) + if new_val != last_val: + await asyncio.create_subprocess_exec('light', '-S', f'{new_val}%', stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL) + await asyncio.sleep(0.005) + last_val = new_val + + if to_value == 0: + await self.switch_display_off() async def brightness_loop(self): self.logger.info('starting brightness loop') while True: if self.brightness_mode != self.brightness_mode_new: - self.logger.info(f'brightness mode changede to {self.brightness_mode_new}') + self.logger.info(f'brightness mode changed to {self.brightness_mode_new}') if self.brightness_mode_new == BrightnessMode.MODE_MAN: await self.dim_screen(50) self.brightness_level = BrightnessLevel.LEVEL_BRIGHT @@ -108,6 +137,7 @@ class DisplayBrightnessManager(): self.brightness_mode = self.brightness_mode_new if self.brightness_mode == BrightnessMode.MODE_AUTO: + self.logger.debug(f'brightness loop begin: {self.last_input}, {time.time()}') if self.last_input + 30 < time.time(): if self.brightness_level != BrightnessLevel.LEVEL_OFF: await self.dim_screen(0) diff --git a/src/ha-kiosk-agent b/src/ha-kiosk-agent index 8842a27..202b1c4 100755 --- a/src/ha-kiosk-agent +++ b/src/ha-kiosk-agent @@ -30,6 +30,7 @@ async def main(): parser.add_argument("--mqtt-port", dest='mqtt_port', default=os.environ.get('MQTT_PORT', 1883)) parser.add_argument("--mqtt-user", dest='mqtt_user', default=os.environ.get('MQTT_USER')) parser.add_argument("--mqtt-pass", dest='mqtt_pass', default=os.environ.get('MQTT_PASS')) + parser.add_argument("--touch-device", dest='touch_device', default=os.environ.get('TOUCH_DEVICE')) args = parser.parse_args() @@ -63,8 +64,8 @@ async def main(): tasks = [] - if args.display_device: - dbm = DisplayBrightnessManager(device, args.display_device, logger) + if args.display_device and args.touch_device: + dbm = DisplayBrightnessManager(device, args.display_device, args.touch_device, logger) tasks.append(dbm.run()) tasks.append(sensor_loop(logger, sensor_entities)) @@ -73,4 +74,4 @@ async def main(): await asyncio.gather(*tasks) if __name__ == "__main__": - asyncio.run(main()) + asyncio.run(main()) diff --git a/src/sensor.py b/src/sensor.py index 4b3156b..2b27ee9 100644 --- a/src/sensor.py +++ b/src/sensor.py @@ -80,35 +80,28 @@ class DisplayBrightnessSensor(): self.mqtt_sensor.set_availability(True) def update_value(self): - res = subprocess.run(['brightnessctl', '-m', 'info'], capture_output=True) + res = subprocess.run(['light', '-G'], capture_output=True) if res.returncode != 0: logger.warn(f'failed to get brightness: exit code { res.returncode }') return - stdout = res.stdout.decode("utf-8") - brightPerc = float(stdout.split(',')[3].split('%')[0]) - + brightPerc = float(res.stdout.decode("utf-8")) if brightPerc != self.value: self.mqtt_sensor.set_value(brightPerc) self.value = brightPerc - def set_display_brightness(self, number: float) -> float: - res = subprocess.run(['brightnessctl', '-m', 'set', f'{ number }%'], capture_output=True) + def set_display_brightness(self, number: float): + res = subprocess.run(['light', '-S', f'{ number }%']) if res.returncode != 0: logger.warn(f'failed to set brightness: exit code { res.returncode }') - return -1 - - stdout = res.stdout.decode("utf-8") - brightPerc = float(stdout.split(',')[3].split('%')[0]) - return brightPerc # To receive number updates from HA, define a callback function: def display_brightness_callback(self, client: Client, user_data, message: MQTTMessage): number = int(message.payload.decode()) logging.info(f"received new value {number} for display brightness") - new_brightness = self.set_display_brightness(number) - self.mqtt_sensor.set_value(new_brightness) + self.set_display_brightness(number) + self.mqtt_sensor.set_value(number) class IPAddressSensor():