Files
Fedora_Brightness_Automatio…/docs/hp-firefly-fedora-brightness-notes.md

14 KiB
Raw Permalink Blame History

HP Firefly G11 unter Fedora finaler sauberer Stand

Ziel

Saubere gemeinsame Helligkeitssteuerung für:

  • internes Display über intel_backlight
  • externen Monitor über ddcutil

sowie automatische Helligkeitsregelung über den vorhandenen Ambient-Light-Sensor mit wluma.

Finale Logik:

  • internes Display ist Master
  • wluma regelt nur noch intel_backlight
  • der externe Monitor wird automatisch auf denselben Prozentwert nachgezogen
  • die manuellen Helligkeitstasten zeigen ein GNOME/Adwaita-passendes OSD
  • dadurch können intern und extern nicht mehr durch zwei unabhängige wluma-Regelungen auseinanderlaufen

Finaler Ist-Zustand

Was aktuell funktioniert

  • Das interne Display hängt als normales Backlight unter:
    • intel_backlight
  • Der externe Monitor HG342PCB am Thunderbolt-Dock ist per ddcutil erreichbar.
  • Die gemeinsamen Button-Skripte regeln jetzt:
    • intern per brightnessctl
    • zeigen ein lokales GTK/libadwaita-OSD
    • extern folgt automatisch über external-brightness-sync.service
  • wluma.service läuft als User-Service nach dem Login.
  • wluma nutzt nur noch das interne intel_backlight.
  • external-brightness-sync.service spiegelt den internen Prozentwert automatisch auf den externen Monitor per ddcutil.

Aktueller Nachweis

systemctl --user status wluma.service
systemctl --user status external-brightness-sync.service
brightnessctl -l
sudo ddcutil detect
sudo ddcutil getvcp 10

Erwarteter sauberer Zustand: in brightnessctl -l:

  • intel_backlight

und in sudo ddcutil detect:

  • Display 1
  • I2C bus: /dev/i2c-16
  • Model: HG342PCB

Warum dieser Stand der richtige ist

1. Internes und externes Display laufen jetzt über zwei stabile Wege

Das interne Panel läuft weiter über intel_backlight. Der externe Monitor wird über das Thunderbolt-Dock direkt per ddcutil angesprochen.

Damit ist die gemeinsame Steuerung wieder stabil, auch wenn intern und extern technisch über unterschiedliche Wege laufen.

Wichtig: Es gibt nur noch eine automatische Regelinstanz. wluma regelt das interne Panel, der Sync-Dienst übernimmt die Spiegelung nach extern.

2. Das Thunderbolt-Dock reicht DDC/CI sauber durch, ddcci_backlight war hier aber nicht der richtige Weg

Mit dem neuen Dock ist der Monitor nachweislich über ddcutil auf card1-DP-5 / /dev/i2c-16 erreichbar. Die frühere ddcci3-Lösung über /sys/class/backlight war für dieses Setup dagegen nicht stabil nutzbar.

Der saubere Endstand ist deshalb:

  • intern: brightnessctl
  • extern: ddcutil
  • kein aggressives Hotplug-Refresh über ddcci

3. GNOME Auto Brightness war nicht funktionsfähig

Der Ambient-Light-Sensor funktioniert eindeutig, aber GNOME hat die Helligkeit sichtbar nicht geregelt. Deshalb ist wluma jetzt die saubere automatische Lösung auf Basis des Sensors.


Aktive Komponenten

Als User aktiv

wluma-Service

~/.config/systemd/user/wluma.service

wluma-Konfiguration

~/.config/wluma/config.toml

Gemeinsame Helligkeitsskripte

~/.local/bin/brightness-osd
~/.local/bin/brightness-ddcutil-hg342pcb
~/.local/bin/brightness-down-all
~/.local/bin/brightness-up-all

Externer Sync-Dienst

~/.local/bin/brightness-sync-hg342pcb
~/.config/systemd/user/external-brightness-sync.service

Finaler Inhalt der wichtigen Dateien

1. ~/.local/bin/brightness-ddcutil-hg342pcb

#!/usr/bin/env bash
set -euo pipefail

MODEL="${BRIGHTNESS_DDCUTIL_MODEL:-HG342PCB}"
STEP="${BRIGHTNESS_DDCUTIL_STEP:-10}"
DISPLAY_NUM="${BRIGHTNESS_DDCUTIL_DISPLAY:-1}"
BUS_NUM="${BRIGHTNESS_DDCUTIL_BUS:-16}"

if [ "$#" -ne 1 ]; then
  echo "Usage: $(basename "$0") up|down" >&2
  exit 2
fi

case "$1" in
  up) delta="+" ;;
  down) delta="-" ;;
  *) echo "Usage: $(basename "$0") up|down" >&2; exit 2 ;;
esac

run_ddcutil() {
  if sudo -n ddcutil --bus "$BUS_NUM" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --bus "$BUS_NUM" "$@"
    return
  fi

  if sudo -n ddcutil --display "$DISPLAY_NUM" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --display "$DISPLAY_NUM" "$@"
    return
  fi

  if sudo -n ddcutil --model "$MODEL" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --model "$MODEL" "$@"
    return
  fi

  if ddcutil --bus "$BUS_NUM" getvcp 10 >/dev/null 2>&1; then
    ddcutil --bus "$BUS_NUM" "$@"
    return
  fi

  if ddcutil --display "$DISPLAY_NUM" getvcp 10 >/dev/null 2>&1; then
    ddcutil --display "$DISPLAY_NUM" "$@"
    return
  fi

  if ddcutil --model "$MODEL" getvcp 10 >/dev/null 2>&1; then
    ddcutil --model "$MODEL" "$@"
    return
  fi

  echo "External HG342PCB was not reachable via ddcutil on bus ${BUS_NUM}." >&2
  exit 1
}

run_ddcutil setvcp 10 "$delta" "$STEP" >/dev/null

2. ~/.local/bin/brightness-down-all

#!/usr/bin/env bash
set -euo pipefail

brightnessctl -q -d intel_backlight set 10%-
/home/jan/.local/bin/brightness-osd || true

3. ~/.local/bin/brightness-up-all

#!/usr/bin/env bash
set -euo pipefail

brightnessctl -q -d intel_backlight set +10%
/home/jan/.local/bin/brightness-osd || true

4. ~/.local/bin/brightness-osd

#!/usr/bin/env python3

Dieses Skript zeigt ein kleines GTK4/libadwaita-OSD am oberen Bildschirmrand mit:

  • Adwaita-Icon display-brightness-symbolic
  • Prozentwert der internen Master-Helligkeit
  • Fortschrittsbalken

Das OSD ist einzeilig und kompakt. Wenn mehrere Tastendrücke schnell hintereinander kommen, wird der laufende OSD-Prozess aktualisiert und der Ausblend-Timer verlängert; dadurch verschwindet es nicht mehr zwischen zwei Helligkeitsänderungen.

Für echte Positionierung am oberen Bildschirmrand unter GNOME Wayland wird dieses Fedora-Paket benötigt:

sudo dnf install -y gtk4-layer-shell

Ohne gtk4-layer-shell darf GNOME/Wayland ein normales GTK-Fenster nicht zuverlässig oben positionieren; dann fällt das Skript auf die normale GTK-Fensterposition zurück.

5. ~/.config/wluma/config.toml

[als.iio]
path = "/sys/bus/iio/devices"
thresholds = { 0 = "night", 20 = "dark", 80 = "dim", 250 = "normal", 500 = "bright", 800 = "outdoors" }

[[output.backlight]]
name = "eDP-1"
path = "/sys/class/backlight/intel_backlight"
capturer = "none"

6. ~/.local/bin/brightness-sync-hg342pcb

#!/usr/bin/env bash
set -euo pipefail

MODEL="${BRIGHTNESS_DDCUTIL_MODEL:-HG342PCB}"
DISPLAY_NUM="${BRIGHTNESS_DDCUTIL_DISPLAY:-1}"
BUS_NUM="${BRIGHTNESS_DDCUTIL_BUS:-16}"
BACKLIGHT_PATH="${BRIGHTNESS_SYNC_BACKLIGHT:-/sys/class/backlight/intel_backlight}"
INTERVAL="${BRIGHTNESS_SYNC_INTERVAL:-1}"
MIN_PERCENT="${BRIGHTNESS_SYNC_MIN_PERCENT:-1}"

brightness_percent() {
  local current max percent

  current="$(<"${BACKLIGHT_PATH}/brightness")"
  max="$(<"${BACKLIGHT_PATH}/max_brightness")"
  percent="$(( (current * 100 + max / 2) / max ))"

  if (( percent < MIN_PERCENT )); then
    percent="$MIN_PERCENT"
  elif (( percent > 100 )); then
    percent=100
  fi

  printf '%s\n' "$percent"
}

run_ddcutil() {
  if sudo -n ddcutil --bus "$BUS_NUM" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --bus "$BUS_NUM" "$@"
    return
  fi

  if sudo -n ddcutil --display "$DISPLAY_NUM" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --display "$DISPLAY_NUM" "$@"
    return
  fi

  if sudo -n ddcutil --model "$MODEL" getvcp 10 >/dev/null 2>&1; then
    sudo -n ddcutil --model "$MODEL" "$@"
    return
  fi

  echo "External ${MODEL} was not reachable via sudo -n ddcutil." >&2
  return 1
}

last_percent=""

while true; do
  percent="$(brightness_percent)"

  if [[ "$percent" != "$last_percent" ]]; then
    if run_ddcutil setvcp 10 "$percent" >/dev/null; then
      last_percent="$percent"
    fi
  fi

  sleep "$INTERVAL"
done

7. ~/.config/systemd/user/wluma.service

[Unit]
Description=Adjust screen brightness automatically with wluma
PartOf=graphical-session.target
After=graphical-session.target

[Service]
ExecStart=/usr/bin/wluma
Restart=always
PrivateNetwork=true
PrivateMounts=false

[Install]
WantedBy=graphical-session.target

8. ~/.config/systemd/user/external-brightness-sync.service

[Unit]
Description=Mirror internal panel brightness to external HG342PCB
PartOf=graphical-session.target
After=graphical-session.target wluma.service

[Service]
ExecStart=%h/.local/bin/brightness-sync-hg342pcb
Restart=always
RestartSec=2

[Install]
WantedBy=graphical-session.target

Dienste finaler Soll-Zustand

Aktiv

systemctl --user status wluma.service
systemctl --user status external-brightness-sync.service

Erwartet:

  • wluma.service: active (running)
  • external-brightness-sync.service: active (running)

Nicht mehr Teil der Lösung

Diese Komponenten gehören nicht mehr zur finalen Lösung:

  • ddcci-attach.service
  • /usr/local/sbin/ddcci-attach-hg342pcb
  • ddcci-refresh.service
  • /usr/local/sbin/ddcci-refresh
  • /etc/udev/rules.d/99-ddcci-hotplug.rules

Der Grund: Mit dem Thunderbolt-Dock funktioniert die externe Steuerung sauber über ddcutil; die ddcci-Backlight-Variante wird dafür nicht mehr benötigt.


Cleanup alter / falscher Komponenten

Falls noch vorhanden: ddcci-refresh entfernen

sudo systemctl disable --now ddcci-refresh.service 2>/dev/null || true
sudo rm -f /etc/systemd/system/ddcci-refresh.service
sudo rm -f /usr/local/sbin/ddcci-refresh
sudo rm -f /etc/udev/rules.d/99-ddcci-hotplug.rules
sudo systemctl daemon-reload
sudo udevadm control --reload-rules

Alte ddcci-Komponenten können entfernt werden

Die ältere ddcci-/ddcci_backlight-Variante ist nicht mehr der finale Stand. Final ist jetzt die Hybrid-Variante über:

  • intel_backlight für intern
  • ddcutil für extern

Bedienung im Alltag

Manuell beide Displays heller / dunkler

/home/jan/.local/bin/brightness-down-all
/home/jan/.local/bin/brightness-up-all

Reaktionsverhalten

Das interne Display reagiert praktisch sofort. Der externe Monitor reagiert typischerweise leicht verzögert, oft ungefähr nach einer Sekunde.

Das ist bei ddcutil normal, weil zuerst DDC/CI-Kommunikation mit dem Monitor über das Dock stattfindet. Etwas schneller könnte es eventuell mit --noverify werden, das ist aber weniger robust und daher aktuell nicht Teil des finalen Stands.

GNOME-Shortcuts

Wenn dafür Benutzerkürzel in GNOME gesetzt werden, immer den vollen Pfad verwenden:

/home/jan/.local/bin/brightness-down-all
/home/jan/.local/bin/brightness-up-all

Nicht ~/.local/bin/..., weil das im GNOME-Shortcut-Feld unzuverlässig sein kann.


wluma und externer Sync aktueller realer Zustand

Wichtig

wluma läuft automatisch nach dem Login und steuert nur das interne Display:

systemctl --user status wluma.service

Der externe Monitor wird durch diesen User-Service nachgezogen:

systemctl --user status external-brightness-sync.service

Verhalten

wluma nutzt weiter den adaptiven Lernmodus, aber nur auf intel_backlight. Der externe Sync-Dienst liest einmal pro Sekunde den internen Prozentwert aus:

/sys/class/backlight/intel_backlight/brightness
/sys/class/backlight/intel_backlight/max_brightness

und setzt denselben Prozentwert extern per:

sudo -n ddcutil --bus 16 setvcp 10 <prozent>

Das bedeutet:

  • wluma entscheidet die Helligkeit nur einmal, am internen Panel
  • extern folgt automatisch
  • manuelle Änderungen über die gemeinsamen Skripte bleiben ebenfalls synchron
  • bei einem Replug des externen Monitors kann ein systemctl --user restart external-brightness-sync.service sinnvoll sein

Praktische Folge

Wenn du möchtest, dass wluma besser wird, dann im Alltag in verschiedenen Lichtsituationen die Helligkeit mit deinen gemeinsamen Skripten nachregeln. Daraus lernt wluma die interne Master-Helligkeit; extern wird automatisch mitgezogen.


Sensorstatus

Der Ambient-Light-Sensor funktioniert sauber.

Nachgewiesen durch:

  • monitor-sensor zeigt deutliche Lux-Änderungen
  • gsettings get org.gnome.settings-daemon.plugins.power ambient-enabled war true
  • iio-sensor-proxy läuft

Das Problem lag daher nicht am Sensor, sondern an GNOME Auto Brightness.


Was bei Problemen sinnvoll ist

1. Prüfen, ob intern und extern erreichbar sind

ls -l /sys/class/backlight
brightnessctl -l
sudo ddcutil --bus 16 getvcp 10

2. Dienste prüfen

systemctl --user status wluma.service
systemctl --user status external-brightness-sync.service

3. Dienste neu starten

systemctl --user restart wluma.service
systemctl --user restart external-brightness-sync.service

Was aktuell bewusst nicht gemacht wird

  • kein aggressives delete_device / new_device im laufenden Betrieb
  • keine Hotplug-Automatik mit ddcci-refresh
  • keine udev-Regel, die ddcci ständig neu erzeugt
  • kein Verlassen auf GNOME Auto Brightness
  • keine unabhängige wluma-Regelung für den externen Monitor

Der Grund ist reine Stabilität: Interner Master plus externer DDC/CI-Sync vermeidet Drift zwischen den Displays.


Kurzfazit

Final sauber gelöst

  • intern läuft über intel_backlight
  • extern läuft über ddcutil auf Bus 16
  • wluma läuft automatisch nach dem Login und steuert nur intern
  • external-brightness-sync.service zieht den externen Monitor automatisch nach
  • der ALS-Sensor funktioniert und wird von wluma genutzt

Final bewusst verworfen

  • externes Display direkt von wluma regeln lassen
  • ddcci-refresh
  • Hotplug-Delete/Recreate-Automatik
  • GNOME Auto Brightness als eigentliche Endlösung

Schnellbefehle

Status

systemctl --user status wluma.service
systemctl --user status external-brightness-sync.service
ls /sys/class/backlight
brightnessctl -l
sudo ddcutil --bus 16 getvcp 10

Manuelle gemeinsame Steuerung

/home/jan/.local/bin/brightness-down-all
/home/jan/.local/bin/brightness-up-all

Dienste neu starten

systemctl --user restart wluma.service
systemctl --user restart external-brightness-sync.service