s.run()
was blocking the the while
loop below from running, so I used multiprocessing to ensure the scheduler and the code for detecting mouse events could run in parallel.
I also changed the method of detecting mouse events to use dev.read_loop()
and used multiprocessing.Value to ensure the variables could be shared between the two processes.
Here is my finished code for anyone who is looking to achieve something similar. It's not perfect by any means; if you touch the screen and the scheduler runs straight after it has no effect, but this is good enough for what I needed:
#! /usr/bin/python3
import sched, throttle, time
from datetime import datetime
from evdev import InputDevice
from select import select
from multiprocessing import Process, Value
# This method calls itself and fades between the current brightness and the target
# brightness
def fade_brightness(check_brightness, target_brightness):
if current_brightness.value != target_brightness.value:
if current_brightness.value > target_brightness.value:
current_brightness.value -= 1
else:
current_brightness.value += 1
file = open("/sys/class/backlight/rpi_backlight/brightness", "w")
file.write(str(current_brightness.value))
file.close()
time.sleep(0.01)
if current_brightness.value != target_brightness.value:
fade_brightness(current_brightness, target_brightness)
# This method is what sets the target brightness and kicks off a fade between the
# current brightness and target brightness. It uses the throttle package
# (https://pypi.org/project/throttle/) to ensure this isn't run repeatedly when
# mouse events are triggered
@throttle.wrap(10, 1)
def set_brightness(brightness, current_brightness, target_brightness):
target_brightness.value = brightness
fade_brightness(current_brightness, target_brightness)
# This method checks whether the screen should be dimmed by default. Here it is set
# to dim the screen if the current time is before 8:30 am or after 10:00 pm
def check_brightness(sc, current_brightness, target_brightness):
now = datetime.now()
time = (now.hour * 100) + now.minute
if time < 830 or time > 2200:
set_brightness(10, current_brightness, target_brightness)
else:
set_brightness(255, current_brightness, target_brightness)
sc.enter(10, 1, check_brightness, (sc, current_brightness, target_brightness))
# This method sets up the scheduler which will call the check_brightness method
def scheduled_brightness(current_brightness, target_brightness):
s = sched.scheduler(time.time, time.sleep)
s.enter(10, 1, check_brightness, (s, current_brightness, target_brightness))
s.run()
# This method sets up the event listener for any mouse event
def pointer_events(current_brightness, target_brightness):
dev = InputDevice('/dev/input/event0')
for event in dev.read_loop():
set_brightness(255, current_brightness, target_brightness)
if __name__=='__main__':
file = open("/sys/class/backlight/rpi_backlight/brightness", "r")
# Set the current brightness to match what's in the brightness file
current_brightness = Value('i', int(file.read()))
target_brightness = Value('i', 255)
p1 = Process(target=scheduled_brightness, args=(current_brightness, target_brightness))
p1.start()
p2 = Process(target=pointer_events, args=(current_brightness, target_brightness))
p2.start()