Question of power-profiles-daemon and dbus net.hadess.PowerProfiles

Hello, I’m developing powermoder. it’s goal is to enable multi performance mode switching based on tlp (or tuned) by allowing the user to switch between multi profiles and even able to run scripts written by the user themselves at the same time. My main goal was to implement a combination of power-profiles-daemon’s multi-mode switching and tlp’s highly customizable features.

After the basics were done, I tried to emulate power-profiles-daemon’s dbus (a.k.a. net.hadess.PowerProfiles) based on powermoder, in order to allow kde’s powerdevil or gnome’s power-panel to control the mode-switching of powermoder via gui. Since I’m not good at C, instead of modifying codes of power-profiles-daemon directly, I’ve tried to use pydbus to provide api that is consistent with net.hadess.PowerProfiles. this program is what I call powermoder2ppd. most of the work has been done so far. powerprofilesctl has been able to work with powermoder2ppd, and gnome or kde can write and choose profiles to run via the gui, but gnome or kde can’t get updates to the active_profile.

Specifically, gnome or kde can learn all the available profiles from powermoder2ppd, and can also learn the active_profile at this moment when powermoder2ppd starts running, and can also modify the active_profile correctly. however, gnome or kde can’t get the update of active_profile, which means that no matter if I use the gui of desktop environment to change active_profile, or use powerprofilesctl or gdbus to change active_profile, gnome or kde won’t show the new active_profile on desktop, but will show the old one, the active_profile at the moment of initialization, and get stuck here forever.

I would certainly like power-profiles-daemon to abstract something like powermoder as an optional driver, or better tlp as driver directly, but I don’t have the ability to provide such a pull request, so as a second option I would like to use my powermoder2ppd to interface with gnome or kde. I don’t have a clue as to what the problem is at the moment, so I hope you can point out what the problem is.
Here is the code for powermoder2ppd. I haven’t dealt with hold related functions yet. other code or files for powermoder can be seen at this [URL]([powermoder2ppd]

Could you tell me how gnome-control-center get update and refresh for the new active_perfile? Thanks.

#!/usr/bin/env python3

import getpass
from gi.repository import GLib
from pydbus import SystemBus
import os

BUS_NAME = 'net.hadess.PowerProfiles'

class FakedNetHadessPowerProfiles:
    dbus = f"""
            <interface name='{BUS_NAME}'>
                <method name='HoldProfile'>
                    <arg name="profile" type="s" direction="in"/>
                    <arg name="reason" type="s" direction="in"/>
                    <arg name="application_id" type="s" direction="in" />
                    <arg name="cookie" type="u" direction="out"/>
                <method name="ReleaseProfile">
                    <arg name="cookie" type="u" direction="in"/>
                <property name="ActiveProfile" type="s" access="readwrite"/>
                <property name="PerformanceInhibited" type="s" access="read"/>
                <property name="PerformanceDegraded" type="s" access="read"/>
                <property name="Actions" type="as" access="read"/>
                <property name="Profiles" type='aa{{sv}}' access="read"/>
                <property name="ActiveProfileHolds" type='aa{{sv}}' access="read"/>

#                <signal name="ProfileReleased">
#                    <arg name="cookie" type="u" direction="out"/>
#                </signal>

    def __init__(self):
        # ActiveProfile
        os.system("/usr/sbin/powermoder config balance")
        #self._active_profile = os.readlink('/etc/powermoder/latest').split('/')[3]
        #if self._active_profile == 'powersave' :
        #    self._active_profile = 'power-saver'
        #elif self._active_profile == 'balanced' :
        #    self._active_profile = 'balance'
        #elif self._active_profile == 'performance' :
        #    self._active_profile = 'performance'
        #else :
        #    self._active_profile = 'balanced'
        # Profiles
        self._profiles = [{'Profile':GLib.Variant('s', 'power-saver'),'Driver':GLib.Variant('s', 'powermoder'),},{'Profile':GLib.Variant('s', 'balanced'),'Driver':GLib.Variant('s', 'powermoder')},{'Profile':GLib.Variant('s', 'performance'),'Driver':GLib.Variant('s', 'powermoder'),}]
        #holds(not support yet)
        #actions(not support yet)
        user = getpass.getuser()
        #print(f'I am running as "{user}"')
    def Profiles(self):
        return self._profiles

    def PerformanceInhibited(self):
        return ''

    def Actions(self):
        return self._actions

    def PerformanceDegraded(self):
        return ''

    def ActiveProfileHolds(self):
        return self._activeprofileholds

    def ActiveProfile(self):
        return self._active_profile

    def ActiveProfile(self, value):
        if value == 'power-saver' :
            self._active_profile = value
            powermode = 'powersave'
        elif value == 'balanced' :
            self._active_profile = value
            powermode = 'balance'
        elif value == 'performance' :
            self._active_profile = value
            powermode = 'performance'
        else :
            powermode = 'balanced'
        os.system(f"""/usr/sbin/powermoder config {powermode}""")
        del powermode

    def HoldProfile(self,profile,reason,application_id):
        return 0

    def ReleaseProfile(cookie):

# It needs to be SystemBus. SessionBus would be used if you start
# your D-Bus service outside of systemd in a terminal.
bus = SystemBus()
bus.publish(BUS_NAME, FakedNetHadessPowerProfiles())
loop = GLib.MainLoop()

Implementing the existing D-Bus API was a good idea. :slight_smile:

See here. It just watches for when the D-Bus property changes.