Skip to content

replace logind polling loops with signal subscriptions - #242

Open
omuhr wants to merge 1 commit into
OpenGamingCollective:mainfrom
omuhr:reduce-logind-spam
Open

replace logind polling loops with signal subscriptions#242
omuhr wants to merge 1 commit into
OpenGamingCollective:mainfrom
omuhr:reduce-logind-spam

Conversation

@omuhr

@omuhr omuhr commented Jul 30, 2026

Copy link
Copy Markdown

Description

Instead of polling OnExternalPower and LidClosed every 2 seconds via D-Bus property calls, subscribe to PropertiesChanged signals from logind.

This eliminates constant D-Bus traffic to logind which was causing slowdowns for other logind callers (e.g. podman, busctl GetUser).

Fixes #235

Monitor of the dbus with the old binary
~ ❯ sudo busctl monitor org.freedesktop.login1                                                                                                             6s

Monitoring bus message stream.
‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=31  Timestamp="Thu 2026-07-30 15:02:13.040007 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1612  ReplyCookie=31  Timestamp="Thu 2026-07-30 15:02:13.040299 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN false;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=32  Timestamp="Thu 2026-07-30 15:02:13.043942 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1613  ReplyCookie=32  Timestamp="Thu 2026-07-30 15:02:13.048347 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=33  Timestamp="Thu 2026-07-30 15:02:15.042075 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1614  ReplyCookie=33  Timestamp="Thu 2026-07-30 15:02:15.042399 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN false;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=34  Timestamp="Thu 2026-07-30 15:02:15.049940 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1615  ReplyCookie=34  Timestamp="Thu 2026-07-30 15:02:15.054424 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=115  Timestamp="Thu 2026-07-30 15:02:16.777252 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=ReleaseDevice
  UniqueName=:1.23
  MESSAGE "uu" {
          UINT32 13;
          UINT32 73;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1616  Timestamp="Thu 2026-07-30 15:02:16.784104 UTC"
  Sender=:1.2  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.2
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.login1.Manager";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "LidClosed";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1617  Timestamp="Thu 2026-07-30 15:02:16.784233 UTC"
  Sender=:1.2  Destination=:1.23  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=PauseDevice
  UniqueName=:1.2
  MESSAGE "uus" {
          UINT32 13;
          UINT32 73;
          STRING "gone";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1618  ReplyCookie=115  Timestamp="Thu 2026-07-30 15:02:16.784288 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "" {
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=116  Timestamp="Thu 2026-07-30 15:02:16.784980 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Peer  Member=Ping
  UniqueName=:1.23
  MESSAGE "" {
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1619  ReplyCookie=116  Timestamp="Thu 2026-07-30 15:02:16.790838 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "" {
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=35  Timestamp="Thu 2026-07-30 15:02:17.043613 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1620  ReplyCookie=35  Timestamp="Thu 2026-07-30 15:02:17.044036 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=36  Timestamp="Thu 2026-07-30 15:02:17.055613 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1621  ReplyCookie=36  Timestamp="Thu 2026-07-30 15:02:17.059770 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=37  Timestamp="Thu 2026-07-30 15:02:19.046166 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1622  ReplyCookie=37  Timestamp="Thu 2026-07-30 15:02:19.046527 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=38  Timestamp="Thu 2026-07-30 15:02:19.061911 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1623  ReplyCookie=38  Timestamp="Thu 2026-07-30 15:02:19.065663 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=117  Timestamp="Thu 2026-07-30 15:02:20.137307 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=TakeDevice
  UniqueName=:1.23
  MESSAGE "uu" {
          UINT32 13;
          UINT32 73;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1624  Timestamp="Thu 2026-07-30 15:02:20.137814 UTC"
  Sender=:1.2  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.2
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.login1.Manager";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "LidClosed";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1625  ReplyCookie=117  Timestamp="Thu 2026-07-30 15:02:20.138319 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "hb" {
          UNIX_FD 5;
          BOOLEAN false;
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=39  Timestamp="Thu 2026-07-30 15:02:21.048979 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1626  ReplyCookie=39  Timestamp="Thu 2026-07-30 15:02:21.049466 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN false;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=40  Timestamp="Thu 2026-07-30 15:02:21.067058 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1627  ReplyCookie=40  Timestamp="Thu 2026-07-30 15:02:21.071663 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=41  Timestamp="Thu 2026-07-30 15:02:23.051181 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "LidClosed";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1628  ReplyCookie=41  Timestamp="Thu 2026-07-30 15:02:23.051486 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN false;
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=42  Timestamp="Thu 2026-07-30 15:02:23.073109 UTC"
  Sender=:1.364  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=Get
  UniqueName=:1.364
  MESSAGE "ss" {
          STRING "org.freedesktop.login1.Manager";
          STRING "OnExternalPower";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1629  ReplyCookie=42  Timestamp="Thu 2026-07-30 15:02:23.077468 UTC"
  Sender=:1.2  Destination=:1.364
  UniqueName=:1.2
  MESSAGE "v" {
          VARIANT "b" {
                  BOOLEAN true;
          };
  };
Logs of the old binary
asusctl HEAD[$!+]❯ sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH RUST_LOG=debug target/release/asusd               10s❄️  🦀
Starting asusd daemon...
[INFO  asusd]        daemon v6.3.11
[INFO  asusd]     rog-anime v6.3.11
[INFO  asusd]     rog-slash v6.3.11
[INFO  asusd]      rog-aura v6.3.11
[INFO  asusd]  rog-profiles v6.3.11
[INFO  asusd] rog-platform v6.3.11
[INFO  asusd] Product family: ROG Zephyrus G16
[INFO  asusd] Board name: GA605WV
[INFO  config_traits] Parsed RON for "asusd::config::Config"
[INFO  rog_platform::platform] Found platform support at "asus-nb-wmi"
[INFO  rog_platform::power] Power: Checking "/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:00/power_supply/BAT1"
[INFO  rog_platform::power] Found a battery
[INFO  rog_platform::power] Checking battery attributes
[INFO  rog_platform::power] Found battery power at "BAT1", matched charge_control_end_threshold. Current level: "90"
[INFO  rog_platform::power] Power: Checking "/sys/devices/pci0000:00/0000:00:08.3/0000:68:00.4/usb7/7-1/7-1.4/7-1.4.2/7-1.4.2:1.1/0003:046D:C082.001A/power_supply/hidpp_battery_2"
[INFO  rog_platform::power] Found a battery
[INFO  rog_platform::power] Power: Checking "/sys/devices/platform/ACPI0003:00/power_supply/ACAD"
[INFO  rog_platform::power] Found mains power at "ACAD"
[INFO  rog_platform::power] Power: Checking "/sys/devices/virtual/misc/uhid/0005:004C:026C.000B/power_supply/hid-c4:14:11:12:18:1d-battery-144"
[INFO  rog_platform::power] Found a battery
[INFO  asusd::asus_armoury] Reloading nv_dynamic_boost
[INFO  asusd::asus_armoury] No saved value for attribute nv_dynamic_boost: skipping.
[INFO  asusd::asus_armoury] Reloading nv_base_tgp
[INFO  asusd::asus_armoury] Reload called on read-only attribute nv_base_tgp: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute nv_base_tgp: skipping.
[INFO  asusd::asus_armoury] Reloading ppt_pl3_fppt
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl3_fppt: skipping.
[INFO  asusd::asus_armoury] Reloading charge_mode
[INFO  asusd::asus_armoury] Reload called on firmware attribute charge_mode
[INFO  asusd::asus_armoury] No saved value for attribute charge_mode: skipping.
[INFO  asusd::asus_armoury] Reloading nv_temp_target
[INFO  asusd::asus_armoury] No saved value for attribute nv_temp_target: skipping.
[INFO  asusd::asus_armoury] Reloading nv_tgp
[INFO  asusd::asus_armoury] No saved value for attribute nv_tgp: skipping.
[INFO  asusd::asus_armoury] Reloading panel_overdrive
[INFO  asusd::asus_armoury] Reload called on firmware attribute panel_overdrive
[INFO  asusd::asus_armoury] Applying value Integer(0) to attribute panel_overdrive
[INFO  asusd::asus_armoury] Restored asus-armoury setting panel_overdrive to Integer(0)
[INFO  asusd::asus_armoury] Reloading ppt_pl1_spl
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl1_spl: skipping.
[INFO  asusd::asus_armoury] Reloading ppt_pl2_sppt
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl2_sppt: skipping.
[INFO  asusd::asus_armoury] Reloading gpu_mux_mode
[INFO  asusd::asus_armoury] Reload called on GPU attribute gpu_mux_mode: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute gpu_mux_mode: skipping.
[INFO  asusd::asus_armoury] Reloading dgpu_disable
[INFO  asusd::asus_armoury] Reload called on GPU attribute dgpu_disable: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute dgpu_disable: skipping.
[INFO  asusd::asus_armoury] Reloading boot_sound
[INFO  asusd::asus_armoury] Reload called on firmware attribute boot_sound
[INFO  asusd::asus_armoury] No saved value for attribute boot_sound: skipping.
[INFO  asusd] attribute on zbus initialized
[INFO  rog_platform::platform] Found platform support at "asus-nb-wmi"
[INFO  asusd::ctrl_fancurves] Device has profile control available
[INFO  asusd::ctrl_fancurves] Device has fan curves available
[INFO  config_traits] Parsed RON for "asusd::ctrl_fancurves::FanCurveConfig"
[INFO  asusd::ctrl_fancurves] Fan curves previously stored, loading...
[INFO  config_traits] Parsed RON for "asusd::ctrl_fancurves::FanCurveConfig"
[INFO  asusd] FanCurves: found supported fancurves
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: CPU, pwm: [2, 12, 38, 56, 68, 73, 104, 104], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: GPU, pwm: [2, 7, 28, 40, 58, 71, 96, 96], temp: [54, 58, 62, 65, 68, 71, 74, 74], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: MID, pwm: [2, 20, 20, 38, 86, 142, 142, 142], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[INFO  asusd] FanCurves: initialized
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:03.1/0000:65:00.0/backlight/nvidia_0"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:08.1/0000:66:00.0/drm/card1/card1-eDP-1/amdgpu_bl1"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:03.1/0000:65:00.0/backlight/nvidia_0"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:08.1/0000:66:00.0/drm/card1/card1-eDP-1/amdgpu_bl1"
[ERROR asusd] Backlight: Missing functionality: No backlights found
[INFO  rog_platform::cpu] Found CPU support at "cpu0", checking supported items
[INFO  rog_platform::cpu] cpufreq/scaling_available_governors: "performance powersave"
[INFO  rog_platform::cpu] cpufreq/scaling_governor: "powersave"
[INFO  rog_platform::cpu] cpufreq/energy_performance_available_preferences: "default performance balance_performance balance_power power custom "
[INFO  rog_platform::cpu] cpufreq/energy_performance_preference: "power"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu0"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu1"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu10"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu11"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu12"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu13"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu14"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu15"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu16"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu17"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu18"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu19"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu2"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu20"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu21"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu22"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu23"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu3"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu4"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu5"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu6"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu7"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu8"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu9"
[INFO  asusd] CtrlPlatform: initialized
[INFO  asusd::ctrl_platform] Starting inotify watch for asusd config file
[INFO  asusd::ctrl_platform] Begin Platform settings restore
[INFO  asusd::ctrl_platform] reloading charge_control_end_threshold to 90
[DEBUG asusd::ctrl_platform] Setting LowPower before EPP
[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)
[INFO  asusd] CtrlPlatform: tasks started
[DEBUG asusd::aura_manager] Testing device "19b6"
[DEBUG asusd::aura_types] Testing for HIDRAW Slash
[INFO  asusd::aura_types] Found slash type GA605_2024: 19b6
[INFO  config_traits] Parsed RON for "asusd::aura_slash::config::SlashConfig"
[DEBUG asusd::aura_slash::trait_impls] reloading slash settings
[DEBUG asusd::aura_types] Testing for laptop aura
[INFO  asusd::aura_types] Found laptop aura type "19b6"
[INFO  rog_platform::keyboard_led] Found keyboard LED controls at "asus::kbd_backlight"
[INFO  asusd::aura_types] Found sysfs backlight control
[INFO  asusd::aura_laptop::config] Setting up AuraConfig for "19b6"
[INFO  rog_aura::aura_detection] Loaded bundled LED support data (embedded)
[INFO  rog_aura::aura_detection] Matched to GA605W
[DEBUG asusd::aura_laptop::config] creating default for Static
[DEBUG asusd::aura_laptop::config] creating default for Breathe
[DEBUG asusd::aura_laptop::config] creating default for RainbowCycle
[DEBUG asusd::aura_laptop::config] creating default for RainbowWave
[DEBUG asusd::aura_laptop::config] creating default for Pulse
[INFO  config_traits] Parsed RON for "asusd::aura_laptop::config::AuraConfig"
[DEBUG asusd::aura_laptop::trait_impls] reloading keyboard mode
[DEBUG asusd::aura_laptop::trait_impls] reloading power states
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 17ef
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 17ef
[DEBUG asusd::aura_types] Testing for USB AniMe
[INFO  asusd::aura_types] No Anime Matrix capable laptop found
[INFO  asusd::aura_manager] Tested device was not AniMe Matrix
[INFO  asusd::aura_manager] Found 2 valid devices on startup
[INFO  asusd] DeviceManager initialized
[INFO  asusd::ctrl_xgm_led] XG Mobile LED not found: Missing functionality: CledDevice::new_from_pattern(): no LED containing 'asus:xgm' found
[INFO  asusd] XG Mobile LED: not present
[INFO  asusd] Startup success on dbus name xyz.ljones.Asusd: begining dbus server loop
Monitor of the dbus with the new binary
~ ❯ sudo busctl monitor org.freedesktop.login1

Monitoring bus message stream.
‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=118  Timestamp="Thu 2026-07-30 15:06:31.265317 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=ReleaseDevice
  UniqueName=:1.23
  MESSAGE "uu" {
          UINT32 13;
          UINT32 73;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1772  Timestamp="Thu 2026-07-30 15:06:31.271987 UTC"
  Sender=:1.2  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.2
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.login1.Manager";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "LidClosed";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1773  Timestamp="Thu 2026-07-30 15:06:31.272074 UTC"
  Sender=:1.2  Destination=:1.23  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=PauseDevice
  UniqueName=:1.2
  MESSAGE "uus" {
          UINT32 13;
          UINT32 73;
          STRING "gone";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1774  ReplyCookie=118  Timestamp="Thu 2026-07-30 15:06:31.272363 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "" {
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=119  Timestamp="Thu 2026-07-30 15:06:31.273023 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Peer  Member=Ping
  UniqueName=:1.23
  MESSAGE "" {
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1775  ReplyCookie=119  Timestamp="Thu 2026-07-30 15:06:31.278101 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "" {
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=120  Timestamp="Thu 2026-07-30 15:06:38.467545 UTC"
  Sender=:1.23  Destination=org.freedesktop.login1  Path=/org/freedesktop/login1/session/_31  Interface=org.freedesktop.login1.Session  Member=TakeDevice
  UniqueName=:1.23
  MESSAGE "uu" {
          UINT32 13;
          UINT32 73;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1776  Timestamp="Thu 2026-07-30 15:06:38.467892 UTC"
  Sender=:1.2  Path=/org/freedesktop/login1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.2
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.login1.Manager";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "LidClosed";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=1777  ReplyCookie=120  Timestamp="Thu 2026-07-30 15:06:38.468406 UTC"
  Sender=:1.2  Destination=:1.23
  UniqueName=:1.2
  MESSAGE "hb" {
          UNIX_FD 5;
          BOOLEAN false;
  };
Logs of the new binary
asusctl reduce-logind-spam[$!+]❯ sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH RUST_LOG=debug target/release/asusd    ❄️  🦀
Starting asusd daemon...
[INFO  asusd]        daemon v6.3.11
[INFO  asusd]     rog-anime v6.3.11
[INFO  asusd]     rog-slash v6.3.11
[INFO  asusd]      rog-aura v6.3.11
[INFO  asusd]  rog-profiles v6.3.11
[INFO  asusd] rog-platform v6.3.11
[INFO  asusd] Product family: ROG Zephyrus G16
[INFO  asusd] Board name: GA605WV
[INFO  config_traits] Parsed RON for "asusd::config::Config"
[INFO  rog_platform::platform] Found platform support at "asus-nb-wmi"
[INFO  rog_platform::power] Power: Checking "/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:00/power_supply/BAT1"
[INFO  rog_platform::power] Found a battery
[INFO  rog_platform::power] Checking battery attributes
[INFO  rog_platform::power] Found battery power at "BAT1", matched charge_control_end_threshold. Current level: "90"
[INFO  rog_platform::power] Power: Checking "/sys/devices/pci0000:00/0000:00:08.3/0000:68:00.4/usb7/7-1/7-1.4/7-1.4.2/7-1.4.2:1.1/0003:046D:C082.001A/power_supply/hidpp_battery_2"
[INFO  rog_platform::power] Found a battery
[INFO  rog_platform::power] Power: Checking "/sys/devices/platform/ACPI0003:00/power_supply/ACAD"
[INFO  rog_platform::power] Found mains power at "ACAD"
[INFO  rog_platform::power] Power: Checking "/sys/devices/virtual/misc/uhid/0005:004C:026C.000B/power_supply/hid-c4:14:11:12:18:1d-battery-144"
[INFO  rog_platform::power] Found a battery
[INFO  asusd::asus_armoury] Reloading nv_dynamic_boost
[INFO  asusd::asus_armoury] No saved value for attribute nv_dynamic_boost: skipping.
[INFO  asusd::asus_armoury] Reloading nv_base_tgp
[INFO  asusd::asus_armoury] Reload called on read-only attribute nv_base_tgp: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute nv_base_tgp: skipping.
[INFO  asusd::asus_armoury] Reloading ppt_pl3_fppt
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl3_fppt: skipping.
[INFO  asusd::asus_armoury] Reloading charge_mode
[INFO  asusd::asus_armoury] Reload called on firmware attribute charge_mode
[INFO  asusd::asus_armoury] No saved value for attribute charge_mode: skipping.
[INFO  asusd::asus_armoury] Reloading nv_temp_target
[INFO  asusd::asus_armoury] No saved value for attribute nv_temp_target: skipping.
[INFO  asusd::asus_armoury] Reloading nv_tgp
[INFO  asusd::asus_armoury] No saved value for attribute nv_tgp: skipping.
[INFO  asusd::asus_armoury] Reloading panel_overdrive
[INFO  asusd::asus_armoury] Reload called on firmware attribute panel_overdrive
[INFO  asusd::asus_armoury] Applying value Integer(0) to attribute panel_overdrive
[INFO  asusd::asus_armoury] Restored asus-armoury setting panel_overdrive to Integer(0)
[INFO  asusd::asus_armoury] Reloading ppt_pl1_spl
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl1_spl: skipping.
[INFO  asusd::asus_armoury] Reloading ppt_pl2_sppt
[INFO  asusd::asus_armoury] No saved value for attribute ppt_pl2_sppt: skipping.
[INFO  asusd::asus_armoury] Reloading gpu_mux_mode
[INFO  asusd::asus_armoury] Reload called on GPU attribute gpu_mux_mode: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute gpu_mux_mode: skipping.
[INFO  asusd::asus_armoury] Reloading dgpu_disable
[INFO  asusd::asus_armoury] Reload called on GPU attribute dgpu_disable: doing nothing
[INFO  asusd::asus_armoury] No saved value for attribute dgpu_disable: skipping.
[INFO  asusd::asus_armoury] Reloading boot_sound
[INFO  asusd::asus_armoury] Reload called on firmware attribute boot_sound
[INFO  asusd::asus_armoury] No saved value for attribute boot_sound: skipping.
[INFO  asusd] attribute on zbus initialized
[INFO  rog_platform::platform] Found platform support at "asus-nb-wmi"
[INFO  asusd::ctrl_fancurves] Device has profile control available
[INFO  asusd::ctrl_fancurves] Device has fan curves available
[INFO  config_traits] Parsed RON for "asusd::ctrl_fancurves::FanCurveConfig"
[INFO  asusd::ctrl_fancurves] Fan curves previously stored, loading...
[INFO  config_traits] Parsed RON for "asusd::ctrl_fancurves::FanCurveConfig"
[INFO  asusd] FanCurves: found supported fancurves
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: CPU, pwm: [2, 12, 38, 56, 68, 73, 104, 104], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: GPU, pwm: [2, 7, 28, 40, 58, 71, 96, 96], temp: [54, 58, 62, 65, 68, 71, 74, 74], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: MID, pwm: [2, 20, 20, 38, 86, 142, 142, 142], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[INFO  asusd] FanCurves: initialized
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:03.1/0000:65:00.0/backlight/nvidia_0"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:08.1/0000:66:00.0/drm/card1/card1-eDP-1/amdgpu_bl1"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:03.1/0000:65:00.0/backlight/nvidia_0"
[INFO  rog_platform::backlight] Backlight: Checking "/sys/devices/pci0000:00/0000:00:08.1/0000:66:00.0/drm/card1/card1-eDP-1/amdgpu_bl1"
[ERROR asusd] Backlight: Missing functionality: No backlights found
[INFO  rog_platform::cpu] Found CPU support at "cpu0", checking supported items
[INFO  rog_platform::cpu] cpufreq/scaling_available_governors: "performance powersave"
[INFO  rog_platform::cpu] cpufreq/scaling_governor: "powersave"
[INFO  rog_platform::cpu] cpufreq/energy_performance_available_preferences: "default performance balance_performance balance_power power custom "
[INFO  rog_platform::cpu] cpufreq/energy_performance_preference: "power"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu0"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu1"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu10"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu11"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu12"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu13"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu14"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu15"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu16"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu17"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu18"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu19"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu2"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu20"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu21"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu22"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu23"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu3"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu4"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu5"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu6"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu7"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu8"
[INFO  rog_platform::cpu] Adding: "/sys/devices/system/cpu/cpu9"
[INFO  asusd] CtrlPlatform: initialized
[INFO  asusd::ctrl_platform] Begin Platform settings restore
[INFO  asusd::ctrl_platform] Starting inotify watch for asusd config file
[INFO  asusd::ctrl_platform] reloading charge_control_end_threshold to 90
[DEBUG asusd::ctrl_platform] Setting LowPower before EPP
[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)
[DEBUG asusd] Doing on_external_power(true)
[DEBUG asusd] Doing on_lid_change(false)
[DEBUG asusd::ctrl_platform] Setting LowPower before EPP
[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)
[INFO  asusd] CtrlPlatform: tasks started
[DEBUG asusd::aura_manager] Testing device "19b6"
[DEBUG asusd::aura_types] Testing for HIDRAW Slash
[INFO  asusd::aura_types] Found slash type GA605_2024: 19b6
[INFO  config_traits] Parsed RON for "asusd::aura_slash::config::SlashConfig"
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: CPU, pwm: [2, 12, 38, 56, 68, 73, 104, 104], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: GPU, pwm: [2, 7, 28, 40, 58, 71, 96, 96], temp: [54, 58, 62, 65, 68, 71, 74, 74], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: MID, pwm: [2, 20, 20, 38, 86, 142, 142, 142], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[INFO  asusd::asus_armoury] Restored armoury setting for panel_overdrive = 0
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::aura_slash::trait_impls] reloading slash settings
[DEBUG asusd::aura_types] Testing for laptop aura
[INFO  asusd::aura_types] Found laptop aura type "19b6"
[INFO  rog_platform::keyboard_led] Found keyboard LED controls at "asus::kbd_backlight"
[INFO  asusd::aura_types] Found sysfs backlight control
[INFO  asusd::aura_laptop::config] Setting up AuraConfig for "19b6"
[INFO  rog_aura::aura_detection] Loaded bundled LED support data (embedded)
[INFO  rog_aura::aura_detection] Matched to GA605W
[DEBUG asusd::aura_laptop::config] creating default for Static
[DEBUG asusd::aura_laptop::config] creating default for Breathe
[DEBUG asusd::aura_laptop::config] creating default for RainbowCycle
[DEBUG asusd::aura_laptop::config] creating default for RainbowWave
[DEBUG asusd::aura_laptop::config] creating default for Pulse
[INFO  config_traits] Parsed RON for "asusd::aura_laptop::config::AuraConfig"
[DEBUG asusd::aura_laptop::trait_impls] reloading keyboard mode
[DEBUG asusd::aura_laptop::trait_impls] reloading power states
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 17ef
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 046d
[DEBUG asusd::aura_manager] Not ASUS vendor ID: 17ef
[DEBUG asusd::aura_types] Testing for USB AniMe
[INFO  asusd::aura_types] No Anime Matrix capable laptop found
[INFO  asusd::aura_manager] Tested device was not AniMe Matrix
[INFO  asusd::aura_manager] Found 2 valid devices on startup
[INFO  asusd] DeviceManager initialized
[INFO  asusd::ctrl_xgm_led] XG Mobile LED not found: Missing functionality: CledDevice::new_from_pattern(): no LED containing 'asus:xgm' found
[INFO  asusd] XG Mobile LED: not present
[INFO  asusd] Startup success on dbus name xyz.ljones.Asusd: begining dbus server loop
[DEBUG asusd] Doing on_lid_change(true)
[DEBUG asusd] Doing on_lid_change(false)

Note the time separation of the events in the monitor for the new binary, the timestamps correspond to when I closed and opened the lid.

Tested Hardware & Environment

  • ASUS Laptop Model: ROG Zephyrus G16 GA605WV_GA605WV (1.0)
  • Linux Distribution: NixOS 25.11 (Xantusia) x86_64
  • Kernel Version: Linux 7.1.5-cachyos

Verification and testing:

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My code follows the style guidelines of this project (cargo fmt --all -- --check)
  • My changes generate no new warnings (cargo clippy --all -- -D warnings/cargo check --all-targets)
  • New and existing unit tests pass locally with my changes (cargo test --all)
  • Cranky with 0 warning (cargo cranky)

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Performance Improvements

    • System events now respond to notifications instead of periodic polling.
    • External power and lid-state changes are detected more efficiently, improving responsiveness and reducing background activity.
    • Initial system state is applied reliably, while repeated or irrelevant events are ignored.
  • Reliability

    • Monitoring failures are logged to make issues easier to diagnose.
    • Power and lid-state monitoring now handles system notifications more consistently.

Walkthrough

asusd replaces periodic lid and external-power polling with logind property events and udev power-supply events. It reads initial state, suppresses duplicate notifications, and logs monitoring failures.

Changes

System-event monitoring

Layer / File(s) Summary
Monitor lid state changes
asusd/src/lib.rs
The lid task reads the initial logind state, consumes property-change events, suppresses repeated values, and invokes callbacks for changes.
Monitor external-power changes
asusd/src/lib.rs
The external-power task discovers the mains supply through sysfs, reads online, and processes matching udev events through a dedicated mio thread. Setup, read, poll, and termination failures are logged.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LidTask
  participant LogindManager
  participant PowerTask
  participant UdevMioThread
  participant Callbacks
  LidTask->>LogindManager: read initial lid state
  LogindManager-->>LidTask: send lid property changes
  LidTask->>Callbacks: invoke callback for changed lid state
  PowerTask->>PowerTask: discover mains supply and read online state
  UdevMioThread->>PowerTask: deliver matching udev changes
  PowerTask->>Callbacks: invoke callback for changed power state
Loading

Possibly related PRs

Suggested labels: asusd, fix

Suggested reviewers: ghoul4500, neroreflex, scardracs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address [#235] by removing frequent logind polling, using signals and udev events, and applying initial state values.
Out of Scope Changes check ✅ Passed The changes remain within scope because udev power monitoring supports the external-power requirement and no unrelated behavior is described.
Title check ✅ Passed The title clearly and concisely describes replacing logind polling with signal subscriptions.
Description check ✅ Passed The description explains the motivation, links issue #235, documents the tested environment, and reports completed verification steps.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added asusd System Daemon / D-Bus fix Fix a bug or an issue labels Jul 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@asusd/src/lib.rs`:
- Around line 272-288: Skip the first cached event from both streams created by
receive_on_external_power_changed and receive_lid_closed_changed, then process
only subsequent change notifications in their respective tokio::spawn loops.
Preserve reload() as the startup-state handler and keep the existing callback
behavior for actual logind changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 23e44506-a1fc-43a8-94e4-00a2349ae9f8

📥 Commits

Reviewing files that changed from the base of the PR and between 4d8a45b and 371a9ec.

📒 Files selected for processing (1)
  • asusd/src/lib.rs
📜 Review details
🔇 Additional comments (1)
asusd/src/lib.rs (1)

21-25: LGTM!

Also applies to: 239-239

Comment thread asusd/src/lib.rs Outdated
Comment thread asusd/src/lib.rs
Comment thread asusd/src/lib.rs

tokio::spawn(async move {
let mut last_lid = manager.lid_closed().await.unwrap_or_default();
// need to loop on these as they don't emit signals

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On several Linux distributions, kernel configurations, and older systemd releases, systemd-logind does not consistently broadcast PropertiesChanged signals for OnExternalPower or LidClosed on the system D-Bus. OnExternalPower is populated via udev/sysfs power_supply rules, but logind's D-Bus interface vtable does not guarantee emits-change-signal="true" for all properties across all systemd versions. Relying solely on stream.next().await without fallback verification or udev event integration will cause asusd to stall indefinitely on systems where logind property signals do not fire.

Comment thread asusd/src/lib.rs Outdated
Comment on lines +241 to +239
.cache_properties(CacheProperties::No)
.cache_properties(CacheProperties::Yes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting CacheProperties::Yes instructs zbus to cache property values locally in memory. If a D-Bus signal is dropped, delayed, or un-emitted by systemd-logind, any call to change.get().await or manager.on_external_power().await will return stale cached values instead of querying systemd-logind directly over D-Bus. For a root-privileged system daemon managing thermal safety and power limits, relying on cached property states without forced invalidation risks operating on stale hardware assumptions.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without CacheProperties enabled I don't get any trigger on lid state change.
It seems to me that the effect of the Cache is that it stores the value (if present) attached to the signal in memory, at least based on this comment on the .get() implementation for PropertyChanged:

impl<T> PropertyChanged<'_, T>
where
    T: TryFrom<zvariant::OwnedValue>,
    T::Error: Into<crate::Error>,
{
    /// Get the value of the property that changed.
    ///
    /// If the notification signal contained the new value, it has been cached already and this call
    /// will return that value. Otherwise (i.e. invalidated property), a D-Bus call is made to fetch
    /// and cache the new value.
    pub async fn get(&self) -> Result<T> {
        self.get_raw()
            .await
            .and_then(|v| T::try_from(OwnedValue::try_from(&*v)?).map_err(Into::into))
    }
}

So wouldn't the cached value correspond to the one communicated by the signal and not a stale value?

Comment thread asusd/src/lib.rs
Comment thread asusd/src/lib.rs
Comment on lines 236 to 242
.expect("Controller could not create dbus connection");

let manager = ManagerProxy::builder(&connection)
.cache_properties(CacheProperties::No)
.cache_properties(CacheProperties::Yes)
.build()
.await
.expect("Controller could not create ManagerProxy");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System daemons running as systemd root services must avoid .expect() and .unwrap() panics during D-Bus setup. If D-Bus is initializing asynchronously during early system boot, asusd should handle D-Bus connection errors gracefully rather than crashing the daemon process.

@scardracs

scardracs commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

To properly eliminate 2-second polling while maintaining total hardware stability, you can test out something like that:

let manager3 = manager.clone();
tokio::spawn(async move {
    // 1. Initial State Fetch & Apply at Daemon Startup (Fixes Boot Issue)
    let mut last_power = match manager3.on_external_power().await {
        Ok(power) => {
            debug!("Initial AC power state on startup: {}", power);
            on_external_power_change(power).await;
            power
        }
        Err(e) => {
            warn!("Failed to read initial AC power state from logind: {}", e);
            false
        }
    };

    // 2. Subscribe to D-Bus Property Change Stream
    let mut stream = manager3.receive_on_external_power_changed().await;

    // 3. Process Signals with Event Deduplication
    while let Some(change) = stream.next().await {
        if let Ok(external_power) = change.get().await {
            if external_power != last_power {
                last_power = external_power;
                debug!("AC power state changed: {}", external_power);
                on_external_power_change(external_power).await;
            }
        }
    }
});

let manager4 = manager.clone();
tokio::spawn(async move {
    // 1. Initial Lid State Fetch & Apply at Daemon Startup
    let mut last_lid = match manager4.lid_closed().await {
        Ok(closed) => {
            debug!("Initial lid state on startup: {}", closed);
            on_lid_change(closed).await;
            closed
        }
        Err(e) => {
            warn!("Failed to read initial lid state from logind: {}", e);
            false
        }
    };

    // 2. Subscribe to D-Bus Property Change Stream
    let mut stream = manager4.receive_lid_closed_changed().await;

    // 3. Process Signals with Event Deduplication
    while let Some(change) = stream.next().await {
        if let Ok(lid_closed) = change.get().await {
            if lid_closed != last_lid {
                last_lid = lid_closed;
                debug!("Lid state changed: {}", lid_closed);
                on_lid_change(lid_closed).await;
            }
        }
    }
});

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
asusd/src/lib.rs (1)

239-239: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Avoid eager property-cache initialization during startup.

With zbus 5.18.0, CacheProperties::Yes waits for cache readiness during build().await and propagates cache errors. The following .expect(...) then panics before the handled property reads. Use CacheProperties::Lazily, or handle proxy-build errors without panicking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` at line 239, Update the proxy builder around
CacheProperties::Yes to use lazy property-cache initialization via
CacheProperties::Lazily, preserving the existing handled property-read flow and
avoiding startup panics from eager cache readiness errors.

Source: MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@asusd/src/lib.rs`:
- Around line 279-282: Update the startup and subsequent property-read handling
for the cached AC-power and lid states in the relevant CtrlPlatform and
AniMeZbus callbacks to use Option<bool>, preserving None when reads fail. Log
every initial and later read error, reset the corresponding cache to None on
failure, and ensure the next valid signal is processed even when it is false
rather than suppressed as unchanged.

---

Outside diff comments:
In `@asusd/src/lib.rs`:
- Line 239: Update the proxy builder around CacheProperties::Yes to use lazy
property-cache initialization via CacheProperties::Lazily, preserving the
existing handled property-read flow and avoiding startup panics from eager cache
readiness errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 11914d2a-1003-4e2c-bb3f-c496ec40de86

📥 Commits

Reviewing files that changed from the base of the PR and between 371a9ec and afffe75.

📒 Files selected for processing (1)
  • asusd/src/lib.rs
📜 Review details
🔇 Additional comments (2)
asusd/src/lib.rs (2)

285-289: 🩺 Stability & Availability

Verify a fallback for systems without logind property signals.

After the startup read, both tasks wait only on receive_*_changed(). If a supported logind/systemd combination does not emit these signals, later AC or lid transitions never reach the callbacks. Retain a low-rate fallback or a guaranteed event source, or narrow and test the supported systemd versions.

This repeats the unresolved signal-availability concern from the previous review.

Also applies to: 315-319


21-25: LGTM!

Also applies to: 272-278, 302-308

Comment thread asusd/src/lib.rs Outdated
Comment on lines +279 to +282
Err(e) => {
warn!("Failed to read initial AC power state from logind: {}", e);
false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve an unknown state after read failures.

Lines 281 and 311 convert a failed startup read into false. If the first valid signal also reports false, Lines 291 and 321 suppress it as unchanged. The CtrlPlatform and AniMeZbus callbacks then do not apply the startup state.

The if let Ok(...) blocks also discard later property-read errors. Use Option<bool>, log each error, and set the cached state to None so the next valid value is processed.

Proposed state handling
-                let mut last_power = match manager3.on_external_power().await {
+                let mut last_power = match manager3.on_external_power().await {
                     Ok(power) => {
                         debug!("Initial AC power state on startup: {}", power);
                         on_external_power_change(power).await;
-                        power
+                        Some(power)
                     }
                     Err(e) => {
                         warn!("Failed to read initial AC power state from logind: {}", e);
-                        false
+                        None
                     }
                 };

                 while let Some(change) = stream.next().await {
-                    if let Ok(external_power) = change.get().await {
-                        if external_power != last_power {
-                            last_power = external_power;
-                            debug!("AC power state changed: {}", external_power);
-                            on_external_power_change(external_power).await;
-                        }
+                    match change.get().await {
+                        Ok(external_power) if last_power != Some(external_power) => {
+                            last_power = Some(external_power);
+                            debug!("AC power state changed: {}", external_power);
+                            on_external_power_change(external_power).await;
+                        }
+                        Ok(_) => {}
+                        Err(e) => {
+                            last_power = None;
+                            warn!("Failed to read AC power state after logind change: {}", e);
+                        }
                     }
                 }

Apply the same pattern to last_lid.

Also applies to: 289-296, 309-312, 319-325

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 279 - 282, Update the startup and subsequent
property-read handling for the cached AC-power and lid states in the relevant
CtrlPlatform and AniMeZbus callbacks to use Option<bool>, preserving None when
reads fail. Log every initial and later read error, reset the corresponding
cache to None on failure, and ensure the next valid signal is processed even
when it is false rather than suppressed as unchanged.

@omuhr

omuhr commented Jul 31, 2026

Copy link
Copy Markdown
Author

The suggested improvements seem good to me and they do solve the original problem I faced.
Apart from the comment about CacheProperties above.

I did discover that my laptop doesn't actually emit OnExternalPower.
I don't know what a good cross-platform solution would be, but UPower does emmit OnBattery for me.

Monitor of `login1` during unplug and replug of AC
~ ❯ sudo busctl monitor org.freedesktop.login1
Monitoring bus message stream.
Monitor of `UPower` during unplug and replug of AC:
~ ❯ sudo busctl monitor org.freedesktop.UPower
Monitoring bus message stream.
‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18212  Timestamp="Fri 2026-07-31 10:39:00.325767 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "Normal";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 48403;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 5,40027;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494340;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,573;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18213  Timestamp="Fri 2026-07-31 10:39:00.326590 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_hidpp_battery_3  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494335;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18214  Timestamp="Fri 2026-07-31 10:39:00.326718 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/line_power_ACAD  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494340;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50197  Timestamp="Fri 2026-07-31 10:39:00.326831 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18215  Timestamp="Fri 2026-07-31 10:39:00.328449 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/DisplayDevice  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494340;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 48403;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 5,40027;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18216  Timestamp="Fri 2026-07-31 10:39:00.328738 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "OnBattery";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18217  ReplyCookie=50197  Timestamp="Fri 2026-07-31 10:39:00.328872 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "BAT1";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "ASUS";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "A32-K55";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494340;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 72,6089;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 72,6089;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 90,0045;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,573;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 80,6726;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 15,93;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "Normal";
                          };
                  };
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18218  Timestamp="Fri 2026-07-31 10:39:00.329583 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18219  Timestamp="Fri 2026-07-31 10:39:00.329801 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/DisplayDevice  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50199  Timestamp="Fri 2026-07-31 10:39:00.330242 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/line_power_ACAD  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18220  ReplyCookie=50199  Timestamp="Fri 2026-07-31 10:39:00.330885 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "ACAD";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494340;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "ac-adapter-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50201  Timestamp="Fri 2026-07-31 10:39:00.331732 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_hidpp_battery_3  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18221  ReplyCookie=50201  Timestamp="Fri 2026-07-31 10:39:00.332336 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "hidpp_battery_3";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "Logitech G Pro";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "10-9a-3f-5e";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494335;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 5;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 86;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50202  Timestamp="Fri 2026-07-31 10:39:00.333056 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_hid_90o9co4ao02o13oc4_battery_144  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18222  ReplyCookie=50202  Timestamp="Fri 2026-07-31 10:39:00.333629 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "hid-90:9c:4a:02:13:c4-battery-144";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "Tangentbord som tillhör Jakob Kallmér";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "90:9c:4a:02:13:c4";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 6;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-missing-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18223  Timestamp="Fri 2026-07-31 10:39:01.332123 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494341;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,555;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18224  Timestamp="Fri 2026-07-31 10:39:02.335746 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494342;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,586;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18225  Timestamp="Fri 2026-07-31 10:39:03.137822 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494343;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18226  Timestamp="Fri 2026-07-31 10:39:03.155412 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/line_power_ACAD  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494343;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18227  Timestamp="Fri 2026-07-31 10:39:03.156597 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "OnBattery";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18228  Timestamp="Fri 2026-07-31 10:39:04.159833 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-charged-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494344;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "Full";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,594;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 4;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18229  Timestamp="Fri 2026-07-31 10:39:04.160236 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/DisplayDevice  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-charged-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494344;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 4;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50203  Timestamp="Fri 2026-07-31 10:39:04.160866 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18230  ReplyCookie=50203  Timestamp="Fri 2026-07-31 10:39:04.161611 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "BAT1";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "ASUS";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "A32-K55";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494344;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 72,6089;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 72,6089;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 90,0045;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,594;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 4;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 80,6726;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-charged-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 15,93;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "Full";
                          };
                  };
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50205  Timestamp="Fri 2026-07-31 10:39:04.162259 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/line_power_ACAD  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18231  ReplyCookie=50205  Timestamp="Fri 2026-07-31 10:39:04.162639 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "ACAD";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494343;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "ac-adapter-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50207  Timestamp="Fri 2026-07-31 10:39:04.163212 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_hidpp_battery_3  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18232  ReplyCookie=50207  Timestamp="Fri 2026-07-31 10:39:04.163354 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "hidpp_battery_3";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "Logitech G Pro";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "10-9a-3f-5e";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494335;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 5;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 86;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 2;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-full-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=50208  Timestamp="Fri 2026-07-31 10:39:04.164092 UTC"
  Sender=:1.42  Destination=org.freedesktop.UPower  Path=/org/freedesktop/UPower/devices/battery_hid_90o9co4ao02o13oc4_battery_144  Interface=org.freedesktop.DBus.Properties  Member=GetAll
  UniqueName=:1.42
  MESSAGE "s" {
          STRING "org.freedesktop.UPower.Device";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=18233  ReplyCookie=50208  Timestamp="Fri 2026-07-31 10:39:04.164615 UTC"
  Sender=:1.48  Destination=:1.42
  UniqueName=:1.48
  MESSAGE "a{sv}" {
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "NativePath";
                          VARIANT "s" {
                                  STRING "hid-90:9c:4a:02:13:c4-battery-144";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Vendor";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Model";
                          VARIANT "s" {
                                  STRING "Tangentbord som tillhör Jakob Kallmér";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Serial";
                          VARIANT "s" {
                                  STRING "90:9c:4a:02:13:c4";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Type";
                          VARIANT "u" {
                                  UINT32 6;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "PowerSupply";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasHistory";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "HasStatistics";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Online";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Energy";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyEmpty";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFull";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyFullDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "EnergyRate";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeCycles";
                          VARIANT "i" {
                                  INT32 -1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Luminosity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToEmpty";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "TimeToFull";
                          VARIANT "x" {
                                  INT64 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Percentage";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Temperature";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsPresent";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "State";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IsRechargeable";
                          VARIANT "b" {
                                  BOOLEAN true;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Capacity";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Technology";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "WarningLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "BatteryLevel";
                          VARIANT "u" {
                                  UINT32 1;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "IconName";
                          VARIANT "s" {
                                  STRING "battery-missing-symbolic";
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeStartThreshold";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeEndThreshold";
                          VARIANT "u" {
                                  UINT32 100;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdEnabled";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSupported";
                          VARIANT "b" {
                                  BOOLEAN false;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "ChargeThresholdSettingsSupported";
                          VARIANT "u" {
                                  UINT32 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMinDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "VoltageMaxDesign";
                          VARIANT "d" {
                                  DOUBLE 0;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "CapacityLevel";
                          VARIANT "s" {
                                  STRING "";
                          };
                  };
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18234  Timestamp="Fri 2026-07-31 10:39:05.163056 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494345;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,989;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18235  Timestamp="Fri 2026-07-31 10:39:06.166285 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494346;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,992;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18236  Timestamp="Fri 2026-07-31 10:39:07.169665 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494347;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,995;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=18237  Timestamp="Fri 2026-07-31 10:39:08.172900 UTC"
  Sender=:1.48  Path=/org/freedesktop/UPower/devices/battery_BAT1  Interface=org.freedesktop.DBus.Properties  Member=PropertiesChanged
  UniqueName=:1.48
  MESSAGE "sa{sv}as" {
          STRING "org.freedesktop.UPower.Device";
          ARRAY "{sv}" {
                  DICT_ENTRY "sv" {
                          STRING "UpdateTime";
                          VARIANT "t" {
                                  UINT64 1785494348;
                          };
                  };
                  DICT_ENTRY "sv" {
                          STRING "Voltage";
                          VARIANT "d" {
                                  DOUBLE 16,997;
                          };
                  };
          };
          ARRAY "s" {
          };
  };

@Ghoul4500 Ghoul4500 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @scardracs mentioned:

OnExternalPower is populated via udev/sysfs power_supply rules, but logind's D-Bus interface vtable does not guarantee emits-change-signal="true" for all properties across all systemd versions.

This would indeed cause issues with Ac/battery transitions. Might be better to watch udev power_supply events instead.

@Ghoul4500

Copy link
Copy Markdown
Member

Also please keep commit history clean when you do bring these changes. Makes for easier review and allows me to rebase and merge more cleanly

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@asusd/src/lib.rs`:
- Around line 289-343: Extract the duplicated initial-read, subscription,
deduplication, and callback flow from the lid and external-power tasks into a
shared generic helper. Have the helper accept an async initial-read closure, the
property-change stream, and the callback, while preserving each source’s value
transformation and failure logging; use it from both tasks and retain the
required Option<bool> tracking behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c9d2dcb3-b456-4146-b50b-68a0dfc3e98d

📥 Commits

Reviewing files that changed from the base of the PR and between afffe75 and e36c383.

📒 Files selected for processing (1)
  • asusd/src/lib.rs
📜 Review details
🔇 Additional comments (3)
asusd/src/lib.rs (3)

244-258: 🩺 Stability & Availability | ⚡ Quick win

.expect() still panics the daemon on D-Bus setup failure.

Connection::system(), ManagerProxy::builder()...build(), and the new UPowerProxy::builder()...build() all use .expect(). A D-Bus error during early boot (logind or UPower not yet available) crashes the daemon process instead of degrading gracefully. This is the same concern raised in a previous review round on this setup block, now also covering the new UPowerProxy line.


289-343: 🎯 Functional Correctness | ⚡ Quick win

Read failures during the stream loop are still silently dropped, and initial failures still collapse to false.

Both tasks share the same gap flagged in a previous review round: Err from logind_manager3.lid_closed() / upower_manager.on_battery() on Line 297 / Line 327 becomes false with only a warn! at startup, and later in the loop, if let Ok(lid_closed) = change.get().await (Line 306) and if let Ok(on_battery) = change.get().await (Line 335) discard Err with no log line at all. If the first valid signal after such a failure also carries false, the dedup check on Line 307 / Line 337 suppresses it as unchanged, and on_lid_change / on_external_power_change never receive the true state.

Track the state as Option<bool>, log every Err from .get(), and reset the cache to None on failure so the next valid value is always applied.

Proposed state handling (apply to both blocks)
-                let mut last_lid = match logind_manager3.lid_closed().await {
+                let mut last_lid: Option<bool> = match logind_manager3.lid_closed().await {
                     Ok(closed) => {
                         debug!("Initial lid state on startup: {}", closed);
                         on_lid_change(closed).await;
-                        closed
+                        Some(closed)
                     }
                     Err(e) => {
                         warn!("Failed to read initial lid state from logind: {}", e);
-                        false
+                        None
                     }
                 };

                 let mut stream = logind_manager3.receive_lid_closed_changed().await;

                 while let Some(change) = stream.next().await {
-                    if let Ok(lid_closed) = change.get().await {
-                        if lid_closed != last_lid {
-                            last_lid = lid_closed;
-                            debug!("Lid state changed: {}", lid_closed);
-                            on_lid_change(lid_closed).await;
-                        }
+                    match change.get().await {
+                        Ok(lid_closed) if last_lid != Some(lid_closed) => {
+                            last_lid = Some(lid_closed);
+                            debug!("Lid state changed: {}", lid_closed);
+                            on_lid_change(lid_closed).await;
+                        }
+                        Ok(_) => {}
+                        Err(e) => {
+                            last_lid = None;
+                            warn!("Failed to read lid state after logind change: {}", e);
+                        }
                     }
                 }

Apply the same pattern to last_power / on_battery.


29-29: LGTM!

Also applies to: 40-49, 260-271, 273-284

Comment thread asusd/src/lib.rs Outdated
Comment on lines 289 to 343
let mut last_lid = match logind_manager3.lid_closed().await {
Ok(closed) => {
debug!("Initial lid state on startup: {}", closed);
on_lid_change(closed).await;
closed
}
Err(e) => {
warn!("Failed to read initial lid state from logind: {}", e);
false
}
};

// 2. Subscribe to D-Bus Property Change Stream
let mut stream = logind_manager3.receive_lid_closed_changed().await;

// 3. Process Signals with Event Deduplication
while let Some(change) = stream.next().await {
if let Ok(lid_closed) = change.get().await {
if lid_closed != last_lid {
last_lid = lid_closed;
debug!("Lid state changed: {}", lid_closed);
on_lid_change(lid_closed).await;
}
}
sleep(Duration::from_secs(2)).await;
}
});

tokio::spawn(async move {
let mut last_lid = manager.lid_closed().await.unwrap_or_default();
// need to loop on these as they don't emit signals
loop {
if let Ok(next) = manager.lid_closed().await {
if next != last_lid {
last_lid = next;
on_lid_change(next).await;
// 1. Initial State Fetch & Apply at Daemon Startup
let mut last_power = match upower_manager.on_battery().await {
Ok(on_battery) => {
let on_external_power = !on_battery;
debug!("Initial AC power state on startup: {}", on_external_power);
on_external_power_change(on_external_power).await;
on_external_power
}
Err(e) => {
warn!("Failed to read initial AC power state from upower: {}", e);
false
}
};
// 2. Subscribe to D-Bus Property Change Stream
let mut stream = upower_manager.receive_on_battery_changed().await;

// 3. Process Signals with Event Deduplication
while let Some(change) = stream.next().await {
if let Ok(on_battery) = change.get().await {
let on_external_power = !on_battery;
if on_external_power != last_power {
last_power = on_external_power;
debug!("AC power state changed: {}", on_external_power);
on_external_power_change(on_external_power).await;
}
}
sleep(Duration::from_secs(2)).await;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared helper for the repeated fetch-then-stream pattern.

The lid-change task (Lines 288-313) and the external-power task (Lines 317-343) implement the same skeleton: read the initial value, log on failure, subscribe to the change stream, dedupe against the last value, and invoke a callback. Only the property source (logind_manager3.lid_closed() vs !upower_manager.on_battery()) and the callback differ. Extract a small generic helper that takes an async initial-read closure, a stream, and a callback, to remove the duplication and keep the fix in one place once the Option<bool> tracking above is applied.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 289 - 343, Extract the duplicated
initial-read, subscription, deduplication, and callback flow from the lid and
external-power tasks into a shared generic helper. Have the helper accept an
async initial-read closure, the property-change stream, and the callback, while
preserving each source’s value transformation and failure logging; use it from
both tasks and retain the required Option<bool> tracking behavior.

@omuhr

omuhr commented Jul 31, 2026

Copy link
Copy Markdown
Author

Also please keep commit history clean when you do bring these changes. Makes for easier review and allows me to rebase and merge more cleanly

Was there something with the current commit history you wanted addressed or just a precautionary comment?

As @scardracs mentioned:

OnExternalPower is populated via udev/sysfs power_supply rules, but logind's D-Bus interface vtable does not guarantee emits-change-signal="true" for all properties across all systemd versions.

This would indeed cause issues with Ac/battery transitions. Might be better to watch udev power_supply events instead.

I commited a first take at this, this approach works for me in detecting AC state changes.
For some reason it does take a few seconds but here is the output of unplugging and replugging the AC adapter:

asusctl logs
[DEBUG asusd] AC power state changed: false
[DEBUG asusd::ctrl_platform] Setting LowPower before EPP
[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: CPU, pwm: [2, 12, 38, 56, 68, 73, 104, 104], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: GPU, pwm: [2, 7, 28, 40, 58, 71, 96, 96], temp: [54, 58, 62, 65, 68, 71, 74, 74], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: MID, pwm: [2, 20, 20, 38, 86, 142, 142, 142], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[INFO  asusd::asus_armoury] Restored armoury setting for panel_overdrive = 0
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd] AC power state changed: true
[DEBUG asusd::ctrl_platform] Setting LowPower before EPP
[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: CPU, pwm: [2, 12, 38, 56, 68, 73, 104, 104], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: GPU, pwm: [2, 7, 28, 40, 58, 71, 96, 96], temp: [54, 58, 62, 65, 68, 71, 74, 74], enabled: false }
[DEBUG rog_profiles] write_profile_curve_to_platform: writing profile:(quiet), CurveData { fan: MID, pwm: [2, 20, 20, 38, 86, 142, 142, 142], temp: [52, 60, 71, 76, 78, 80, 82, 82], enabled: false }
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[INFO  asusd::asus_armoury] Restored armoury setting for panel_overdrive = 0
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] Tuning group is not enabled, skipping
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed
[DEBUG asusd::asus_armoury] panel_overdrive changed

I dont know if this warning is related to the delay?

[WARN  asusd::ctrl_platform] Failed to set platform profile LowPower on AC/BAT change: platform_profile Operation not supported (os error 95)

I initially looked at using upower_dbus but it is using an old version of zbus which depends on an old version of rustix that doesn't compile anymore.
It also didn't seem to like receiving a zbus connection created with a newer version of zbus.
All that was needed was

#[proxy(
    interface = "org.freedesktop.UPower",
    default_service = "org.freedesktop.UPower",
    default_path = "/org/freedesktop/UPower"
)]
trait UPower {
    #[zbus(property)]
    fn on_battery(&self) -> zbus::Result<bool>;
}

which I clumsily dropped near the top of asusd/src/lib.rs.
I expect there is a much more fitting place, but I don't know enough about the code base to tell if this change should affect other parts as well, like this and this for example.

UPower also provides lid state changes via LidIsClosed if that is interesting.

I also don't know that this is even a portable solution, or if some combination of UPower and logind is the solution.

@Ghoul4500

Ghoul4500 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Was there something with the current commit history you wanted addressed or just a precautionary comment?

I was pointing out that you were making a new commit for addressing review comments instead of doing fixup onto the original commit and force pushing. You should amend the original commit as force push in this case

Also as per our commit convention you can write the message as "fix: [rest of message]" or similar

I will review this again shortly. Thank you for your work on this

@Ghoul4500 Ghoul4500 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't recommend this approach. Not all devices may have UPower. A udev monitor is probably the best here still. If you are unfamiliar with it I could bring the changes to this PR myself and squash merge

@omuhr
omuhr force-pushed the reduce-logind-spam branch 2 times, most recently from 56f7b05 to 591a074 Compare July 31, 2026 23:27
Instead of polling OnExternalPower and LidClosed every 2 seconds via
D-Bus property calls, subscribe to PropertiesChanged signals from
logind.

This eliminates constant D-Bus traffic to logind which was causing
slowdowns for other logind callers (e.g. podman, busctl GetUser).

Fixes OpenGamingCollective#235

update with suggested improvements

move to upower for getting external power state (first draft)

move to udev monitoring

debloat

forgot
@omuhr
omuhr force-pushed the reduce-logind-spam branch from 591a074 to e8587c9 Compare July 31, 2026 23:31
@omuhr

omuhr commented Jul 31, 2026

Copy link
Copy Markdown
Author

I still don't recommend this approach. Not all devices may have UPower. A udev monitor is probably the best here still. If you are unfamiliar with it I could bring the changes to this PR myself and squash merge

I had missed your recommendation of udev :)

I took a stab at it, I wasn't quite sure how to handle the multi-threading of udev::MonitorSocket and error management in the thread in general.

Feedback appreciated!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@asusd/src/lib.rs`:
- Around line 428-430: Update the external power supply monitoring fallback in
the surrounding initialization flow to use error-level logging instead of
warn-level logging, and include the specific failure cause: either
/sys/class/power_supply was unreadable or no power-supply entry had type
"Mains".
- Around line 388-421: Update the change-event handling around
power_supply_monitor.iter() to fall back to reading the external power supply’s
sysfs online value when property_value("POWER_SUPPLY_ONLINE") is absent. Use the
matched device sysname to read /sys/class/power_supply/<sysname>/online, parse
its value into the same boolean state, and only warn and skip when both sources
are unavailable or invalid; preserve the existing state-change comparison and
on_external_power_change call.
- Around line 322-337: Update the external power-supply initialization around
the `and_then` chain to keep a discovered mains supply even when reading its
initial `online` file fails; log the read error and represent the initial state
as unknown rather than returning `None`. Start the udev monitor whenever supply
discovery succeeds, and change `last_power_supply_state` in the monitor thread
to `Option<bool>` so unknown initial state is handled without suppressing future
change events.
- Around line 344-345: Update the external-power handling around
tokio::runtime::Handle::current and the spawned udev monitor thread so it sends
power-state changes through a channel instead of synchronously waiting for the
callback. Add a Tokio task that receives channel messages and performs the
potentially slow AniMe USB callback, keeping the udev polling loop non-blocking
and preserving each power-state change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d30161fe-61cb-47d7-b787-34fe112d71a9

📥 Commits

Reviewing files that changed from the base of the PR and between e36c383 and e8587c9.

📒 Files selected for processing (1)
  • asusd/src/lib.rs
📜 Review details
🔇 Additional comments (6)
asusd/src/lib.rs (6)

234-242: Connection::system() and ManagerProxy::builder(...).build() still panic the daemon on failure. This was raised in a previous review on this same range.


278-301: The failure path still stores false as a real state, so a first false signal is suppressed and on_lid_change never runs. Errors from change.get() are also discarded. Use Option<bool> and log the error. This was raised in a previous review.


24-24: LGTM!


244-272: LGTM!


346-386: LGTM!


310-321: 🎯 Functional Correctness

Confirm whether supported ASUS hardware can expose multiple Mains supplies.

Linux permits multiple power-supply devices, and drivers can classify USB-PD ports as Mains. This code selects one sysname and drops events from the others. If any supported model exposes multiple Mains supplies, collect all matching sysnames and compute the logical OR of their online values.

Comment thread asusd/src/lib.rs
Comment on lines +322 to +337
.and_then(|sysname| {
// Look up the initial state of the external power supply
let path = std::path::PathBuf::from("/sys/class/power_supply")
.join(&sysname)
.join("online");
let state = std::fs::read_to_string(&path)
.map_err(|e| {
error!(
"Could not read external power supply state from {path:?}: {e}"
)
})
.ok()
.map(|s| s.trim() != "0")?;
Some((sysname, state))
})
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not disable monitoring when only the initial online read fails.

The second and_then returns None if reading online fails. The whole if let Some(...) block is then skipped, so the udev monitor never starts and no external-power change is ever reported for the rest of the daemon lifetime. A transient read error should not disable event monitoring permanently.

Separate supply discovery from the initial state read. Start the monitor whenever a mains supply is found, and treat an unreadable initial state as unknown.

🛠️ Proposed restructure
-            if let Some((external_power_supply_sysname, initial_power_supply_state)) =
+            if let Some(external_power_supply_sysname) =
                 std::fs::read_dir("/sys/class/power_supply")
                     .ok()
                     .and_then(|dir| {
                         // Look up the external power supply sysname (e.g. "ACAD") by finding one
                         // with the type "mains"
                         dir.flatten().find_map(|entry| {
                             let type_path = entry.path().canonicalize().ok()?.join("type");
                             let supply_type = std::fs::read_to_string(type_path).ok()?;
                             supply_type
                                 .trim()
                                 .eq_ignore_ascii_case("mains")
                                 .then(|| entry.file_name().to_string_lossy().to_string())
                         })
                     })
-                    .and_then(|sysname| {
-                        // Look up the initial state of the external power supply
-                        let path = std::path::PathBuf::from("/sys/class/power_supply")
-                            .join(&sysname)
-                            .join("online");
-                        let state = std::fs::read_to_string(&path)
-                            .map_err(|e| {
-                                error!(
-                                    "Could not read external power supply state from {path:?}: {e}"
-                                )
-                            })
-                            .ok()
-                            .map(|s| s.trim() != "0")?;
-                        Some((sysname, state))
-                    })
             {
-                debug!(
-                    "External power supply plugged in on startup: {}",
-                    initial_power_supply_state
-                );
-                on_external_power_change(initial_power_supply_state).await;
+                let online_path = std::path::PathBuf::from("/sys/class/power_supply")
+                    .join(&external_power_supply_sysname)
+                    .join("online");
+                let mut initial_power_supply_state = match std::fs::read_to_string(&online_path) {
+                    Ok(s) => Some(s.trim() != "0"),
+                    Err(e) => {
+                        error!("Could not read external power supply state from {online_path:?}: {e}");
+                        None
+                    }
+                };
+                if let Some(state) = initial_power_supply_state {
+                    debug!("External power supply plugged in on startup: {}", state);
+                    on_external_power_change(state).await;
+                }

Then track last_power_supply_state as Option<bool> in the monitor thread.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 322 - 337, Update the external power-supply
initialization around the `and_then` chain to keep a discovered mains supply
even when reading its initial `online` file fails; log the read error and
represent the initial state as unknown rather than returning `None`. Start the
udev monitor whenever supply discovery succeeds, and change
`last_power_supply_state` in the monitor thread to `Option<bool>` so unknown
initial state is handled without suppressing future change events.

Comment thread asusd/src/lib.rs
Comment on lines +344 to +345
let handle = tokio::runtime::Handle::current();
std::thread::spawn(move || {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate the tokio runtime construction and the tokio feature set for asusd.
fd -t f 'Cargo.toml' | xargs rg -n -C3 'tokio'

# Find the runtime entry point / macro attributes.
rg -nP -C5 '#\[tokio::main[^\]]*\]|Builder::new_(multi_thread|current_thread)|Runtime::new\(\)' --type=rust

Repository: OpenGamingCollective/asusctl

Length of output: 2306


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- workspace Tokio features ---'
sed -n '58,78p' Cargo.toml
printf '%s\n' '--- asusd entry points and runtime setup ---'
rg -nP -C8 '#\[tokio::main[^\]]*\]|Builder::new_(multi_thread|current_thread)|Runtime::new\(\)|fn main' asusd --glob '*.rs'
printf '%s\n' '--- target call sites ---'
sed -n '320,435p' asusd/src/lib.rs
printf '%s\n' '--- monitor and callback implementations ---'
rg -n -C8 'poll\.poll|on_external_power_change|external_power|AniMe|hid|usb' asusd/src --glob '*.rs'

Repository: OpenGamingCollective/asusctl

Length of output: 50385


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- create_sys_event_tasks and caller ---'
sed -n '190,345p' asusd/src/lib.rs
printf '%s\n' '--- external-power callback wiring ---'
rg -n -C10 'create_sys_event_tasks|set_power_states|set_power|external_power' asusd/src --glob '*.rs'
printf '%s\n' '--- AniMe power callback methods ---'
rg -n -C12 'set_power_states|power_state|external_power|on_external' asusd/src/aura_anime --glob '*.rs'
printf '%s\n' '--- AniMe implementation outline and relevant body ---'
ast-grep outline asusd/src/aura_anime/trait_impls.rs

Repository: OpenGamingCollective/asusctl

Length of output: 44013


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
from pathlib import Path
import re

workspace = Path("Cargo.toml").read_text()
daemon = Path("asusd/src/daemon.rs").read_text()
lib = Path("asusd/src/lib.rs").read_text()
anime = Path("asusd/src/aura_anime/trait_impls.rs").read_text()

features = re.search(r'tokio\s*=\s*\{.*?features\s*=\s*\[(.*?)\]', workspace, re.S)
assert features and '"rt-multi-thread"' in features.group(1), "workspace lacks rt-multi-thread"
assert re.search(r'#\[tokio::main\]\s*async\s+fn\s+main', daemon), "asusd does not use the default Tokio main macro"
assert "handle.block_on(on_external_power_change" in lib, "target block_on call not found"

callback = re.search(
    r'move \|power_plugged\|.*?async move \{(.*?)\n\s*\},',
    anime,
    re.S,
)
assert callback, "AniMe external-power callback not found"
assert ".write_bytes(" in callback.group(1), "callback has no device write"
assert ".await" in callback.group(1), "callback has no awaited operation"

print("runtime_flavor=multi_thread (workspace feature + default #[tokio::main])")
print("foreign_thread_block_on=present")
print("anime_external_power_callback=async device writes present")
PY

Repository: OpenGamingCollective/asusctl

Length of output: 329


Move external-power handling off the udev monitor thread.

asusd uses Tokio's multi-thread runtime, so Handle::block_on from this thread is valid. However, the call blocks until the callback completes. Slow AniMe USB writes can delay poll.poll, allowing the udev socket queue to overflow and lose power-state changes. Send state changes through a channel to a Tokio task instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 344 - 345, Update the external-power handling
around tokio::runtime::Handle::current and the spawned udev monitor thread so it
sends power-state changes through a channel instead of synchronously waiting for
the callback. Add a Tokio task that receives channel messages and performs the
potentially slow AniMe USB callback, keeping the udev polling loop non-blocking
and preserving each power-state change.

Comment thread asusd/src/lib.rs
Comment on lines +388 to 421
for event in power_supply_monitor.iter() {
if event.event_type() != udev::EventType::Change {
continue;
}
if event.device().sysname().to_string_lossy()
!= external_power_supply_sysname
{
continue;
}

let Some(current_power_supply_state) = event
.device()
.property_value("POWER_SUPPLY_ONLINE")
.map(|v| v != "0")
else {
warn!(
"Power supply change event for external power supply \
missing POWER_SUPPLY_ONLINE property, skipping..."
);
continue;
};

if current_power_supply_state != last_power_supply_state {
last_power_supply_state = current_power_supply_state;
debug!(
"External power supply state changed: {}",
current_power_supply_state
);
handle.block_on(on_external_power_change(
current_power_supply_state,
));
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Re-read online from sysfs instead of relying only on the uevent property.

The handler skips any change event that does not carry POWER_SUPPLY_ONLINE. The kernel does not guarantee that every change uevent for a power supply includes the full property set. When the property is missing, the daemon logs a warning and keeps the previous state, so a real transition can be lost permanently.

Fall back to reading /sys/class/power_supply/<sysname>/online when the property is absent.

🛠️ Proposed fallback
-                                let Some(current_power_supply_state) = event
-                                    .device()
-                                    .property_value("POWER_SUPPLY_ONLINE")
-                                    .map(|v| v != "0")
-                                else {
-                                    warn!(
-                                        "Power supply change event for external power supply \
-                                         missing POWER_SUPPLY_ONLINE property, skipping..."
-                                    );
-                                    continue;
-                                };
+                                let device = event.device();
+                                let current_power_supply_state = match device
+                                    .property_value("POWER_SUPPLY_ONLINE")
+                                    .map(|v| v != "0")
+                                {
+                                    Some(state) => state,
+                                    None => {
+                                        let path = std::path::PathBuf::from(
+                                            "/sys/class/power_supply",
+                                        )
+                                        .join(&external_power_supply_sysname)
+                                        .join("online");
+                                        match std::fs::read_to_string(&path) {
+                                            Ok(s) => s.trim() != "0",
+                                            Err(e) => {
+                                                warn!(
+                                                    "Power supply change event missing \
+                                                     POWER_SUPPLY_ONLINE and {path:?} is \
+                                                     unreadable: {e}"
+                                                );
+                                                continue;
+                                            }
+                                        }
+                                    }
+                                };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for event in power_supply_monitor.iter() {
if event.event_type() != udev::EventType::Change {
continue;
}
if event.device().sysname().to_string_lossy()
!= external_power_supply_sysname
{
continue;
}
let Some(current_power_supply_state) = event
.device()
.property_value("POWER_SUPPLY_ONLINE")
.map(|v| v != "0")
else {
warn!(
"Power supply change event for external power supply \
missing POWER_SUPPLY_ONLINE property, skipping..."
);
continue;
};
if current_power_supply_state != last_power_supply_state {
last_power_supply_state = current_power_supply_state;
debug!(
"External power supply state changed: {}",
current_power_supply_state
);
handle.block_on(on_external_power_change(
current_power_supply_state,
));
}
}
}
for event in power_supply_monitor.iter() {
if event.event_type() != udev::EventType::Change {
continue;
}
if event.device().sysname().to_string_lossy()
!= external_power_supply_sysname
{
continue;
}
let device = event.device();
let current_power_supply_state = match device
.property_value("POWER_SUPPLY_ONLINE")
.map(|v| v != "0")
{
Some(state) => state,
None => {
let path = std::path::PathBuf::from(
"/sys/class/power_supply",
)
.join(&external_power_supply_sysname)
.join("online");
match std::fs::read_to_string(&path) {
Ok(s) => s.trim() != "0",
Err(e) => {
warn!(
"Power supply change event missing \
POWER_SUPPLY_ONLINE and {path:?} is \
unreadable: {e}"
);
continue;
}
}
}
};
if current_power_supply_state != last_power_supply_state {
last_power_supply_state = current_power_supply_state;
debug!(
"External power supply state changed: {}",
current_power_supply_state
);
handle.block_on(on_external_power_change(
current_power_supply_state,
));
}
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 388 - 421, Update the change-event handling
around power_supply_monitor.iter() to fall back to reading the external power
supply’s sysfs online value when property_value("POWER_SUPPLY_ONLINE") is
absent. Use the matched device sysname to read
/sys/class/power_supply/<sysname>/online, parse its value into the same boolean
state, and only warn and skip when both sources are unavailable or invalid;
preserve the existing state-change comparison and on_external_power_change call.

Comment thread asusd/src/lib.rs
Comment on lines +428 to +430
} else {
warn!("External power supply monitoring unavailable");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Raise the log level and name the failure cause.

If no mains supply is found, external-power tracking is silently disabled for the whole daemon lifetime. Power profiles, fan curves, and dGPU power states then never react to AC changes. This is a functional loss, not a routine condition.

Use error! and include the reason, for example that /sys/class/power_supply was unreadable or that no entry has type == "Mains".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@asusd/src/lib.rs` around lines 428 - 430, Update the external power supply
monitoring fallback in the surrounding initialization flow to use error-level
logging instead of warn-level logging, and include the specific failure cause:
either /sys/class/power_supply was unreadable or no power-supply entry had type
"Mains".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asusd System Daemon / D-Bus fix Fix a bug or an issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

asusd seems to be overloading logind

3 participants