Linux Stromverbrauch und Restlaufzeit schick anzeigen

Linux Betriebssystem

elarei

Well-known member
Themenstarter
Registriert
2 Aug. 2009
Beiträge
3.323
Hi,

ich habe die letzten Tage ein Skript für Ubuntu geschrieben, um meinen Stromverbrauch am X1 Nano im Auge zu behalten. Geht aber im Prinzip mit jedem Thinkpad. Ich habe es so gebastelt, dass beim Entladen die letzten fünf Minuten gemittelt werden und auf dieser Basis der Stromverbrauch angezeigt und die Restlaufzeit berechnet wird. So erhält man einen etwas konstanteren Wert als beim Rechnen mit dem aktuellen Stromverbrauch, der gerne mal stark schwankt.

Zur Anzeige habe ich das Gnome-Plugin "Argos" verwendet, das aber nur auf xorg und nicht auf Wayland funktioniert. Man muss auf dem Anmeldebildschirm auf xorg umschalten, damit das Plugin in 22.04 läuft. Alternativ kann man natürlich das Skript auch aus Conky heraus aufrufen, dann sieht man es halt nur auf dem Desktop. Ich finde es in der Top Bar sehr gut aufgehoben.

Meine Dateien liegen in ~/.conkysettings, weil ich es parallel auch für Conky verwende. Das Ganze ist ein bisschen gewachsener Code, deshalb ist es nicht besonders aufgeräumt, aber es funktioniert (bei mir) prima.

Viele Grüße

(Codeupdate auf Grundlage der bisherigen Rückmeldungen vom 13.12. : )
Bash:
#!/bin/bash

# Get the current battery power in milliwatts
power_now=$(cat /sys/class/power_supply/BAT0/power_now)
power_now_display=$(($power_now / 1000000))

# Calculate the current battery percentage
energy_now=$(cat /sys/class/power_supply/BAT0/energy_now)
energy_full=$(cat /sys/class/power_supply/BAT0/energy_full)
battery_percent=$(($energy_now * 100 / $energy_full))

# Calculate the average power draw over the last n*slepetime seconds, e.g. 120 x 5 = 10 minutes
tail -n 120 /dev/shm/battery_log.txt > /dev/shm/battery_temp.txt
sleep 1
mv /dev/shm/battery_temp.txt /dev/shm/battery_log.txt
echo $(($power_now / 1000000)) >> /dev/shm/battery_log.txt
battery_avg=$(awk '{ sum += $1 } END { print sum / NR }' /dev/shm/battery_log.txt)
battery_avg_display=$(printf "%.1f \n" $battery_avg)

# Calculate the estimated time left on the battery
state=$(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep "state")
if [[ $state == *"discharging"* ]]; then
  on_ac=false
elif [[ $state == *"charging"* ]]; then
  is_charging=true
else
  is_charging=false
fi
charge_now=$(cat /sys/class/power_supply/BAT0/energy_now)
power_left=$(($charge_now / 1000))
power_left_wh=$(($charge_now / 1000000))
charge_full=$(cat /sys/class/power_supply/BAT0/energy_full)
charge_full_wh=$(($charge_full / 1000000))
charge_full_design=$(cat /sys/class/power_supply/BAT0/energy_full_design)
charge_full_design_wh=$(($charge_full_design / 1000000))
current_rate=$(($power_now / 1000))
current_rate_watt=$(($current_rate / 1000))
if [ $current_rate -gt 0 ]; then
  battery_avg_sed=$(sed "s/,/./" <<< $battery_avg_display)
  secs=$(echo "scale=0;$power_left * 3.6 / $battery_avg_sed" | bc -l)
  time_left=$(printf '%d:%d\n' $((secs/3600)) $((secs%3600/60)))
  hours_left=$(printf '%d\n' $((secs/3600)))
  minutes_left=$(printf '%d\n' $((secs%3600/60)))
  printf -v minutes_left "%02d" $minutes_left
  time_full=$(($charge_full / $current_rate))
  time_design=$(($charge_full_design / $current_rate))
else
  time_left=0
  time_full=0
  time_design=0
fi
# Output the battery information
if [[ $on_ac == false ]]; then
  output="Entlade mit $battery_avg_display W ($hours_left:$minutes_left h @ $power_left_wh/$charge_full_wh Wh, $battery_percent%)"
elif [[ $is_charging == true ]]; then
  output="Lade mit $power_now_display W ($power_left_wh/$charge_full_wh Wh, $battery_percent%)"
else
  output="Geladen ($power_left_wh/$charge_full_wh Wh, $battery_percent%)"
fi
echo $output
 
Zuletzt bearbeitet:
Zwei Anmerkungen:

1. Du benutzt ~/.conkysettings/battery_log.txt und ~/.conkysettings/battery_temp.txt als Shared Memory um Informatioen zwischen zwei Aufrufen des Scripts zu transportieren.
Für diesen Zweck sieht der FHS /dev/shm vor, was ein tmpfs ist. Das hätte den Vorteil, dass du nicht jede Sekunde eine Schreiboperation auf die Home-SSD ausführst. Sicher steht dein Script nicht im Verdacht eine SSD kaputtzuschreiben, aber auch Kleinvieh macht Mist und am Ende geht's um's Prinzip.
Falls dir /dev/shm zu unsicher ist (RAM könnte volllaufen - nicht durch dein Script), dann könntest du die Datei nach /tmp schreiben. So hätte der User indirekt selbst die Kontrolle darüber, denn es ist üblich /tmp wahlweise als tmpfs zu mounten, oder eben nicht.

2. Du liest fix /sys/class/power_supply/BAT0 aus, was der erste Akku im System ist. Wenn du BAT0 über einen Parameter an das Script übergibst, dann könnte dein Script auch mit mehreren Akkus umgehen, indem man den Parameter (z.B. BAT1) anpasst.
 
  • Like
Reaktionen: Tao
Bei GNOME wird normalerweise rechts oben ein Icon mit dem Füllstand des Akkus angezeigt. Im Drop-Down-Menü gibt's dann Details - Was macht Dein Script besser?

Verstehe auch nicht warum für den logfile-Anteil nicht soetwas wie RRDtool genutzt wird.
 
Danke für den Tipp mit dem RAM-Pfad, das könnte man tatsächlich gut machen. Ich fand die bisherige Lösung sehr unschön, aber ich hab wenig Ahnung von Linux und auf Anhieb nichts besseres gesehen.

Die Idee ist ja gerade, einerseits die Anzeige live auf dem Schirm zu lassen und nicht erst aufklappen zu müssen (was ich schon komfortabler finde, sonst könnte ich auch nach Conky rüberwechseln), und andererseits einen gemittelten und insofern halbwegs verlässlichen Verbrauch zu verwenden anstelle der sehr sprunghaften Schätzungen, die aus dem direkten Verrechnen des gerade aktuellen Power Draw resultieren.
 
Könnte man nicht iwie auch die Werte aus powertop oder TLP anzeigen lassen bzw einbinden? Die Werte meinte ich zumindest zu glauben seien doch ziemlich akkurat, oder irre ich mich?
 
Könnte man nicht iwie auch die Werte aus powertop oder TLP anzeigen lassen bzw einbinden?
Die lesen auch nur /sys/class/power_supply aus.
Der Knackpunkt ist hier nicht, an die Messwerte heranzukommen, sondern sie statistisch aufzubereiten und dem Nutzer zu präsentieren. Und wenn @elarei mit den bestehenden Aufbereitungsformen unzufrieden ist, dann muss er seine Eigene definieren.
Beitrag automatisch zusammengeführt:

Noch eine dritte Anmerkung:
Code:
# Calculate the estimated time left on the battery
state=$(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep "state")
if [[ $state == *"discharging"* ]]; then
  on_ac=false
else
  on_ac=true
Streng genommen ist der Rückschluss, dass ein sich entladender Akku bedeutet, dass kein Netzteil angeschlossen ist nicht richtig. Das Notebook könnte auch gerade mehr Strom verbrauchen als das angeschlossene Netzteil liefern kann. Auch dann entlädt sich der Akku.
Das hat funktional auf das Script keine Auswirkung, aber da man sich die Belegung und Verwertung von $on_ac im Script auch ganz sparen kann, würde das auch die Klarheit des Codes erhöhen.

Ob der Akku gerade geladen wird oder nicht, könnte man außerdem aus /sys/class/power_supply/BAT0/status erfahren. Dafür bräuchte man nicht extra upower aufrufen.
 
Zuletzt bearbeitet:
Warum so kompliziert? Alle Informationen liegen schön aufbereitet in /sys/... und "acpi" gibt die Daten auch freiwillig her, z.B."acpi -a" liefer den Status des Netzteils :)
 
File access vs. Subprocess. Davon abgesehen ist ggf noch ein Paket zu installieren
 
Warum das Rad neu erfinden? Gibt doch bereits eine Unzahl von Plasmoids, die den Energieverbrauch monitorn und grafisch darstellen.
 
Vielleicht ist die Idee ja nicht klar genug formuliert. Ein zentrales Ding, das mich an den vorhandenen Möglichkeiten stört und das ich hier lösen will, ist die ständige Hüpferei der prognostizierten Laufzeiten, wenn man diese auf der Grundlage der aktuellen ebenfalls ständig hüpfenden power_now ausrechnet. acpi und die integrierte Prognose unter dem Batteriesymbol machen das vermutlich genau so, ist ja auch die einfachste Lösung. Aber: Zwischen zwei Aufrufen von acpi --battery im Abstand von 60 Sekunden, als ich eben damit gespielt habe, hatte ich einmal 3:12 remaining und einmal 5:07 remaining. Das sind auch irgendwie Prognosen, aber keine besonders hilfreichen. In diesem Sinne hat hikaru es schon richtig verstanden:
Der Knackpunkt ist hier nicht, an die Messwerte heranzukommen, sondern sie statistisch aufzubereiten und dem Nutzer zu präsentieren.
Plasmoids: Klingt nach KDE?
Alle Informationen liegen schön aufbereitet in /sys/...
Wenn es da ein Log des Stromverbrauchs gibt, wäre das tatsächlich eine Vereinfachung, aber ich hab zumindest auf Anhieb nichts gefunden.
 
Zuletzt bearbeitet:
Ein zentrales Ding, das mich an den vorhandenen Möglichkeiten stört und das ich hier lösen will, ist die ständige Hüpferei der prognostizierten Laufzeiten, wenn man diese auf der Grundlage der aktuellen ebenfalls ständig hüpfenden power_now ausrechnet.
Um das vielleicht ein wenig anders auszudrücken:
Dein Script gibt das arithmetische Mittel der (Ent-)Ladung über die letzten fünf Minuten aus und glättet so (Ent-)Ladespitzen.
 
Plasmoids: Klingt nach KDE?
Wird doch sicher auch für andere Desktops sowas geben.

Das Schöne an Open Soure ist, daß man die Programme modifizieren kann. Du muß halt den Teil der Laufzeitberechnung anpassen, der Rest kann bleiben.

Aber: die Aufgabe ist nicht so leicht wie du denkst. Das Problem ist schlimmer als der ominöse Fortschrittsbalken bei SW-Installern. Du willst eine brauchbare Prognose über die Restlaufzeit machen. Ein Mittlung über 5 Minuten beseitigt dein Problem der ungenügenden Prognosegüte nicht. Du kannst damit Schwankungen glätten, und die Anzeige träger machen - mehr nicht. Was hast Du davon?
Aus dem aktuellen Stromverbrauch kannst nichts über den künftigen aussagen. Angenommen, der Rechner ist idle, dann startest du einen Rendertask, die Laufzeitprognose nimmt aufgrund der Glättungsfunktion nur langsam ab, nach der Beendigung des Rendertasks hinkt sie dann wieder der Realität hinterher. Den Nutzen kann ich nicht erkennen.
 
Dem widerspreche ich entschieden! Klar kann ich nicht die Zukunft vorhersagen, aber wenn ich in Excel Zahlen eintippe, möchte ich doch haben, dass die Restlaufanzeige ungefähr damit zu tun hat, was ich in dieser Arbeitsphase für einen Durchschnittsverbrauch habe. Was ich nicht möchte, ist in der einen Sekunde die Hälfte von dem, was in der nächsten Sekunde dasteht, weil irgendein Hintergrundprozess für zehn Sekunden die CPU angeworfen hat. Solche Zahlen sind Blödsinn. Gemittelte Zahlen über x Minuten sind es natürlich in geringerem Maße auch, aber trotzdem sind sie erheblich klarer kalkulierbar und ich behaupte, dass die Restlaufzeit so sehr viel plausibler und bei gleichbleibendem Nutzungsprofil viel zuverlässiger ermittelt werden kann. Immerhin kann man zwar nicht in die Zukunft sehen, aber doch grob davon ausgehen, dass das Nutzungsprofil der letzten x Minuten sich wahrscheinlich so weiterzieht, und wenn der Verbrauch plötzlich dauerhaft steigt, pendelt sich die Anzeige nach x Minuten darauf ein.
 
Versuche dein Glück! Aber du nennst schon das Problem:
und ich behaupte, dass die Restlaufzeit so sehr viel plausibler und bei gleichbleibendem Nutzungsprofil viel zuverlässiger ermittelt werden kann.
Was ist ein gleichbleibendes Nutzungsprofil?

Nimm z.B. die Reichweitenanzeige eines PKWs - ein offensichtlich viel einfacher zu lösendes Problem, da der Verbrauch eines PKWs nicht so wild rumspringt wie der eines Rechners. Dennoch macht die Reichweitenanzeige immer wieder überraschende Sprünge - jedenfalls bei mein Audi - obwohl ich recht konstant unterwegs bin. Schaffe ich es noch bis zur billigen Tankstelle auf dem Heimweg oder muß ich gleich an der teuren Tankstelle an der Ausfallstraße zur Autobahn tanken? Eine ohne ersichtlichen Grund rasant von 50km auf 0km abfallende Reichweitenanzeige ist auf der AB im nirgendwo immer pulssteigernd.

Die Heuristik, die sich die Audi-Ingenieure überlegt haben, scheint so manchmal komische Effekte zu produzieren.

Du willst es besser machen. Wohlan!
 
  • ok1.de
  • IT Refresh - IT Teile & mehr
  • thinkstore24.de
  • Preiswerte-IT - Gebrauchte Lenovo Notebooks kaufen

Werbung

Zurück
Oben