Abonnieren Sie das DBUS-Ereignis „Bildschirm ausschalten“

Abonnieren Sie das DBUS-Ereignis „Bildschirm ausschalten“

Mein MacBook Pro hat eine Tastaturbeleuchtung, die ziemlich toll ist, aber es gibt einen kleinen Fehler: Der Bildschirm schaltet sich nach einer bestimmten Zeit aus, aber die Tastaturbeleuchtung bleibt an.

Ich habe ein kleines DBUS-Python-Skript kopiert und damit herumgespielt, um zu überwachen, wann sich der Bildschirmschonerstatus ändert. Es wird jedoch nicht ausgelöst, wenn der Bildschirm ausgeht, sondern nur, wenn der Bildschirmschoner aktiviert oder deaktiviert wird:

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()

Dies funktioniert einwandfrei, wenn der Bildschirmschoner aktiviert ist, wird aber nicht geändert, wenn sich der Energiestatus des Bildschirms ändert, was unabhängig vom Bildschirmschoner passieren kann. Unter „Helligkeit und Sperren“ in den Einstellungen können Sie festlegen, dass sich die Bildschirme nach 1 Minute ausschalten und nicht sperren. Sie können dann die Bildschirmschonerzeit auf eine andere Zeitspanne einstellen, beispielsweise 10 Minuten.

Ich habe versucht, über die org.gnome.SettingsDaemon.Power.ScreenSchnittstelle auf das ChangedSignal zu lauschen, aber das passiert nur, wenn die Bildschirmhelligkeit manuell geändert wird.

Worauf kann ich achten, um festzustellen, wann sich der Bildschirm-Stromversorgungszustand geändert hat? Ich möchte ein Skript schreiben, das ausgeführt wird, wenn der Bildschirm ausgeschaltet wird, sodass ich die Hintergrundbeleuchtung meiner Tastatur deaktivieren kann.

Antwort1

Nun, es ist schade, dass ich keinen Kommentar hinterlassen kann, weil ich nicht den „Ruf“ habe. Das ist eher ein Kommentar als eine Lösung.

Ich habe nach etwas Ähnlichem gesucht und überwache stattdessen „org.gnome.SessionManager.Presence“. Hinter meinem Monitor befinden sich LEDs für die Hintergrundbeleuchtung, und ich möchte sie mit dem Monitor ein- und ausschalten.

Dies funktioniert, wenn ich meinen Computer manuell sperre. Wenn ich jedoch die Einstellungen „Bildschirm aus“ und „Bildschirm sperren nach“ auf unterschiedliche Intervalle setze, schalten sich die LEDs aus, wenn der Monitor ausgeschaltet wird. Wenn jedoch die Bildschirmschonersperre greift, schalten sich die LEDs wieder ein.

_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
}

Referenz: https://www.organicdesign.co.nz/PoisonTap_solution

Antwort2

Ich habe gerade Ubuntu 18.04 installiert und es stellt sich heraus, dass standardmäßig kein Bildschirmschoner vorhanden ist. Und ehrlich gesagt will ich keinen, also werde ich mir nicht die Mühe machen, einen zu installieren.

Ich habe jedoch einige Methodenaufrufe von Gnome gefunden, die den Zweck zu erfüllen scheinen: AddUserActiveWatchund RemoveWatchvon org.gnome.Mutter.IdleMonitorder Schnittstelle.

Hier ist mein Skript:

#!/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 ()

Das Ergebnis ist:

  • Wenn das Display dunkler wird, wird die Hintergrundbeleuchtung meiner Tastatur ausgeschaltet
  • die Tastatur leuchtet erst auf, NACHDEM ich mich erfolgreich angemeldet habe, nicht auf dem Anmeldebildschirm (aber es kommt dem schon ziemlich nahe)

Haftungsausschluss:

  1. Das Wort Monitor in org.gnome.Mutter.IdleMonitor kommt von der Überwachungsaktion, nicht vom Monitor, auch bekannt als Bildschirm. Im Grunde genommen scheinen dies also Methoden zu sein, die aufgerufen werden, wenn der Benutzer von Gnome als inaktiv und nicht als inaktiv erklärt wird. Tatsächlich fällt dies in meinem Fall mit dem Ausschalten des Bildschirms zusammen. In Ihrem Fall ist dies möglicherweise nicht der Fall.
  2. Anscheinend kann man das nicht als systemd-Eintrag hinzufügen, da es einen Bildschirm benötigt. Man kann es jedoch in der Startup ApplicationsGUI hinzufügen und es funktioniert
  3. Ich verwende die ausführbare Datei g810-led, um die Hintergrundbeleuchtung meiner Tastatur ein- und auszuschalten. Dies sollte nur als Beispiel betrachtet werden, da es auf anderen Tastaturen offensichtlich nicht funktioniert

PS: habe einen "Bug" gefunden. Unterbricht man die Bildschirmausblendung, bleibt die Tastatur unbeleuchtet.

Antwort3

Okay, also nachJahreAnstatt darüber frustriert zu sein, habe ich endlich etwas dagegen unternommen und ein Python-Hilfsskript geschrieben, das DBus überwacht und Sitzungssperr-/Entsperrereignisse ordnungsgemäß empfängt.

DerDer Code wird hier gehostet, aber ich werde es auch unten einfügen. Mein Ziel ist es, dies aus mehreren Gründen in Rust neu zu schreiben, aber hauptsächlich, um es für die Leute einfacher zu machen, es zu verwenden, ohne Pakete installieren zu müssen, um die richtigen Python-Bibliotheken zu installieren.


Voraussetzungen

Um diesen Code auszuführen, benötigen Sie:

  • Ein aktuelles Python 3, ich habe dies in Python 3.8.5 geschrieben.
  • Eier:
    • dbus-python >=1.2,<2
    • PyGObject >=3.36,<4

Diese Python-Eggs werden von bestimmten Ubuntu-Paketen bereitgestellt, sind aber möglicherweise nicht die richtigen Versionen. Für 16.04 sind meines Erachtens die folgenden Pakete erforderlich:

  • python3-gi, welches istPyGObject
  • python3-dbus, welches istdbus-python

Bei verschiedenen Distributionsversionen können diese Pakete unterschiedlich sein. Dies ist einer der vielen Gründe, warum ich dies in Rust neu schreiben möchte. Meine anderen Beweggründe werde ich am Ende dieser Antwort auflisten.

Code

Schauen wir uns den Code an.

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()

Um diesem Code interessante Aktionen zu verleihen, bearbeiten Sie Folgendes:

  • ScreenSaverEventListener.on_session_lock, das ausgeführt wird, wenn der Bildschirm gesperrt ist

verwandte Informationen