Mi MacBook Pro tiene una retroiluminación del teclado que es bastante impresionante, pero hay un pequeño error: la pantalla se apaga después de un tiempo determinado, pero la retroiluminación del teclado permanece encendida.
Copié y modifiqué un pequeño script DBUS Python para monitorear cuándo se producen cambios en el estado del protector de pantalla, pero no se activa cuando la pantalla se apaga, solo cuando el protector de pantalla se activa o desactiva:
from dbus.mainloop.glib import DBusGMainLoop
import dbus
import gobject
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
dbus_loop = DBusGMainLoop(set_as_default=True)
def message_callback(bus, message):
if message.get_interface() == "org.gnome.ScreenSaver":
if message.get_member() == "ActiveChanged":
screensaver_enabled = bool(message.get_args_list()[0])
logger.info("Screen saver changed. Active: %s", screensaver_enabled)
session = dbus.SessionBus(mainloop=dbus_loop)
session.add_match_string_non_blocking("interface='org.gnome.ScreenSaver'")
session.add_message_filter(message_callback)
logger.info("Starting up.")
loop = gobject.MainLoop()
loop.run()
Esto funciona muy bien siempre que se activa el protector de pantalla, pero no se modifica si cambia el estado de energía de la pantalla, lo que puede suceder independientemente del protector de pantalla. Al ir a Brillo y Bloqueo en Configuración, puede configurar las pantallas para que se apaguen después de 1 minuto y no se bloqueen. Luego puede configurar el tiempo del protector de pantalla en una cantidad de tiempo diferente, digamos 10 minutos.
Intenté escuchar org.gnome.SettingsDaemon.Power.Screen
la Changed
señal en la interfaz, pero esto solo sucede cuando el brillo de la pantalla se cambia manualmente.
¿Qué puedo escuchar para determinar cuándo ha cambiado el estado de energía de la pantalla? Quiero escribir un script que se ejecute cada vez que se apague la pantalla para poder desactivar la luz de fondo del teclado.
Respuesta1
Bueno, es una pena que no pueda dejar un comentario porque no tengo la "reputación". Esto es más un comentario que una solución.
He estado buscando algo similar y en su lugar estoy monitoreando 'org.gnome.SessionManager.Presence'. Tengo LED detrás de mi monitor para iluminación polarizada y quiero apagarlos/encenderlos con el monitor.
Esto funciona si bloqueo mi computadora manualmente, sin embargo, si dejo las configuraciones de "pantalla apagada" y "pantalla de bloqueo después" en diferentes intervalos, los LED se apagan cuando el monitor se apaga, sin embargo, cuando se activa el bloqueo del protector de pantalla, se apaga. Los LED se encienden nuevamente.
_getState () {
dbus-monitor --session "type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged" |
while read x; do
case "$x" in
*"uint32 3"*)
/home/victor/bin/devices/kasa_cntrl.sh off
echo -e "$(date)\t-\tTurned off" >> "$log"
;;
*"uint32 0"*)
/home/victor/bin/devices/kasa_cntrl.sh on
echo -e "$(date)\t-\tTurned on" >> "$log"
;;
esac
done
}
Referencia: https://www.organicdesign.co.nz/PoisonTap_solution
Respuesta2
Acabo de instalar Ubuntu 18.04 y resulta que no hay ningún protector de pantalla predeterminado. Y, sinceramente, no quiero uno, así que no me molestaré en instalarlo.
Sin embargo, encontré algunas llamadas a métodos de gnome que parecen funcionar: AddUserActiveWatch
y RemoveWatch
desde org.gnome.Mutter.IdleMonitor
la interfaz.
Aquí está mi guión:
#!/usr/bin/env python
import dbus, gobject
from dbus.mainloop.glib import DBusGMainLoop
from subprocess import call
def filter_cb(bus,message):
if message.get_member() == "AddUserActiveWatch":
print("Monitor off")
call("/usr/bin/g810-led -dv 046d -dp c337 -a 000000", shell=True)
elif message.get_member() == "RemoveWatch":
print("Monitor on")
call("/usr/bin/g810-led -dv 046d -dp c337 -p /etc/g810-led/profile", shell=True)
return
DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
bus.add_match_string_non_blocking("interface='org.gnome.Mutter.IdleMonitor',eavesdrop='true'")
bus.add_message_filter(filter_cb)
mainloop = gobject.MainLoop ()
mainloop.run ()
El resultado es:
- cuando la pantalla comienza a atenuarse, la luz de fondo de mi teclado se apaga
- el teclado se ilumina solo DESPUÉS de iniciar sesión correctamente, no en la pantalla de inicio de sesión (pero está lo suficientemente cerca)
Descargos de responsabilidad:
- La palabra monitor en org.gnome.Mutter.IdleMonitor proviene de la acción de monitoreo, no del monitor, también conocido como pantalla. Básicamente, estos parecen ser métodos que se llaman cuando gnome declara al usuario inactivo y no inactivo. De hecho, en mi caso coincide con el apagado de la pantalla. En tu caso, puede que no sea así.
- Aparentemente no puedes agregar esto como una entrada systemd porque necesita una pantalla. Sin embargo, puedes agregarlo en la
Startup Applications
GUI y funciona. - Estoy usando el ejecutable g810-led para encender y apagar la luz de fondo de mi teclado, esto debería tratarse solo como un ejemplo, ya que obviamente no funcionará en otros teclados.
PD: encontré un "error". Si interrumpes el desvanecimiento de la pantalla, el teclado permanece apagado.
Respuesta3
Está bien, entonces despuésañosSin estar frustrado con esto, finalmente hice algo al respecto y escribí un script de utilidad Python que monitorea DBus y recibe adecuadamente los eventos de bloqueo/desbloqueo de sesión.
ElEl código está alojado aquí., pero también lo incluiré a continuación. Mi objetivo es reescribir esto en Rust por varias razones, pero principalmente para que sea más fácil de usar para las personas sin tener que instalar paquetes para instalar las bibliotecas de Python correctas.
Requisitos previos
Para ejecutar este código, necesitará:
- Un Python 3 reciente, escribí esto en Python 3.8.5.
- Huevos:
dbus-python >=1.2,<2
PyGObject >=3.36,<4
Estos huevos de Python los proporcionan ciertos paquetes de Ubuntu, pero es posible que no sean las versiones correctas. El 16.04, creo que los paquetes requeridos son:
python3-gi
, cual esPyGObject
python3-dbus
, cual esdbus-python
En diferentes versiones de distribución, estos paquetes pueden ser diferentes. Esta es una de las muchas razones por las que quiero reescribir esto en Rust. Enumeraré mis otras motivaciones al final de esta respuesta.
Código
Entremos en el código.
dbus-session-lock-watcher.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
import dbus
import logging
import sys
class ScreenSaverEventListener(object):
def __init__(self):
self.logger = logging.getLogger(self.__class__.__name__)
self.mainloop = DBusGMainLoop()
self.loop = GLib.MainLoop()
self.session_bus = dbus.SessionBus(mainloop=self.mainloop)
self.receiver_args, self.receiver_kwargs = None, None
def setup(self):
self.receiver_args = (self.on_session_activity_change,)
self.receiver_kwargs = dict(dbus_interface="org.freedesktop.DBus.Properties", path="/org/gnome/SessionManager",
signal_name="PropertiesChanged",
# callback arguments
sender_keyword="sender", destination_keyword="dest",
interface_keyword="interface", member_keyword="member", path_keyword="path",
message_keyword="message")
self.session_bus.add_signal_receiver(*self.receiver_args, **self.receiver_kwargs)
def on_session_activity_change(self, target: dbus.String, changed_properties: dbus.Dictionary, *args, **kwargs):
if target != "org.gnome.SessionManager" or "SessionIsActive" not in changed_properties:
return
if changed_properties.get("SessionIsActive"):
self.on_session_unlock()
else:
self.on_session_lock()
def on_session_lock(self):
self.logger.info("Session Locked")
def on_session_unlock(self):
self.logger.info("Session Unlocked")
def run(self):
self.logger.debug("Starting event loop.")
self.loop.run()
def shutdown(self):
self.logger.debug("Stopping event loop.")
self.session_bus.remove_signal_receiver(*self.receiver_args, **self.receiver_kwargs)
self.loop.quit()
def main():
setup_logging()
listener = ScreenSaverEventListener()
listener.setup()
try:
listener.run()
except KeyboardInterrupt:
sys.stderr.write("ctrl+c received, shutting down...\n")
listener.shutdown()
def setup_logging():
console = logging.StreamHandler(sys.stderr)
console.setFormatter(
logging.Formatter("%(asctime)s [%(levelname)-5s] %(name)s: %(message)s", datefmt="%Y-%m-%dT%H:%M:%S%z"))
logging.addLevelName(logging.WARNING, "WARN")
logging.getLogger().addHandler(console)
logging.getLogger().setLevel(logging.DEBUG)
if __name__ == "__main__":
main()
Para que este código haga algo interesante, edite:
ScreenSaverEventListener.on_session_lock
, que se ejecutará cuando la pantalla se haya bloqueado