From 46c893be36efc2201554319b5370b063cb539bc8 Mon Sep 17 00:00:00 2001 From: eleksir Date: Tue, 25 Feb 2020 22:49:09 +0300 Subject: [PATCH] Add i3status-timers.dbus --- i3status-timers.dbus | 302 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 i3status-timers.dbus diff --git a/i3status-timers.dbus b/i3status-timers.dbus new file mode 100644 index 0000000..87c0a80 --- /dev/null +++ b/i3status-timers.dbus @@ -0,0 +1,302 @@ +#!/usr/bin/perl +# vim: set ai noet ts=8 sw=8 sts=8 ft=perl : + +# set username +# set uptime +# set time +# set xtitle of focused window +# set list of windows for current tag +# set list of windows for all tags +# set la +# set current language +# set battery charge + +# main loop impl. : +# save cur. str and compare it with prev. if it differs - update + +# proposed: 3 types of loop: +# slow loop for batt charge, la +# 1 second loop for time, uptime - generally, it looks like we do not need poll every second +# timers if clock granularity set to 1 minute or even coarse +# main (fast) loop for window name, language, it looks like we have some room here for greater +# improvement, when it'll be more clear how get info directly from x server + +use strict; +use warnings "all"; + +use Fcntl qw(:seek); +use Net::DBus; + + +binmode STDOUT; +binmode STDERR; + +sub onesec_cron(); +sub slow_cron(); + +sub gettimestr(); +sub getfocusedwidowtitlestr(); +sub getlangstr(); +sub getuptimestr(); +sub getlastr(); +sub getbatterychargestr1(); +sub getbatterychargestr2(); +sub getbatterychargestr3(); +sub meminfo(); +sub to_hours($); # translates seconds to HH:MM format + + +my $slow_timer = 360; # 0.333 * 360 ~= 2 min +my $onesec_timer = 3; # 0.333 * 3 ~= 1 sec + +my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); +my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); + +my $pstr = ''; + +my $charge; +my $la; +my $uptime; +my $time; +my $mem; + +my $bus = Net::DBus->system; +my $upower = $bus->get_service("org.freedesktop.UPower"); +my $properties = $upower->get_object("/org/freedesktop/UPower/devices/battery_BAT0", "org.freedesktop.DBus.Properties"); + +my $UPTIMEHANDLE; +my $LAHANDLE; +my $MEMINFOHANDLE; + +sleep 1; + +while (1) { + if ($onesec_timer >= 3) { + onesec_cron(); + $onesec_timer = 0; + } + + if ($slow_timer >= 360) { + slow_cron(); + $slow_timer = 0; + } + + my $str = ''; +# $str .= getfocusedwidowtitlestr(); +# $str .= "$ENV{'USER'}"; + $str .= getlangstr(); + $str .= $uptime; + $str .= $la; + $str .= $mem; + $str .= $charge; + $str .= $time; + + if ($pstr ne $str) { + syswrite STDOUT, "$str\n"; + $pstr = $str; + } + +# tick timers + $slow_timer++; + $onesec_timer++; + +# sleep for 0.333 second; + select(undef, undef, undef, 0.333); +} + +sub slow_cron() { + $charge = getbatterychargestr3(); + $la = getlastr(); +} + +sub onesec_cron() { + $uptime = getuptimestr(); + $time = gettimestr(); +# as we report time with precision of 1 minute, update 1/60 seconds + $mem = meminfo(); +} + + +sub gettimestr() { + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; + $year = $year + 1900; + my $str .= sprintf(" | %s, %s %s %s %02s:%02s ", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min); + + return $str; +} + +sub getfocusedwidowtitlestr() { + my $str; + + if (-x '/usr/bin/xdotool') { + $str = `xdotool getactivewindow getwindowname`; + } elsif (-x '/usr/bin/xprop') { + $str = (split( / = /, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; + chop $str; chop $str; + } + + chomp($str); + + if (length($str) != 0) { + if (length($str) > 64){ + $str = '...' . substr($str, 0, -61); + } + $str = '['. $str .'] | '; + } else { + $str = '| '; + } + + return $str; +} + +sub getuptimestr() { + if (defined($UPTIMEHANDLE)) { + open $UPTIMEHANDLE, "/proc/uptime" if (tell($UPTIMEHANDLE) == -1); + } else { + open $UPTIMEHANDLE, "/proc/uptime"; + } + + my $u = <$UPTIMEHANDLE>; + seek $UPTIMEHANDLE, SEEK_SET, 0; + $u = (split(/ /, $u, 2))[0]; + my $days = int($u / 86400); # 86400 = 1 day + my $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour + my $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); + my $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); + my $str = sprintf(" | up: %sd,%02sh,%02sm ", $days, $hours, $minutes); + + return $str; +} + +sub getlastr() { + if (defined($LAHANDLE)) { + open $LAHANDLE, "/proc/loadavg" if (tell($LAHANDLE) == -1); + } else { + open $LAHANDLE, "/proc/loadavg"; + } + + my $la = <$LAHANDLE>; + seek $LAHANDLE, SEEK_SET, 0; + $la = (split(/ /, $la, 2))[0]; + + return (" | LA: $la "); +} + +sub getbatterychargestr1() { + my $str = ''; + + if (-f "/sys/class/power_supply/BAT0/present") { + open A, "/sys/class/power_supply/BAT0/present"; + my $P = ; + close A; + chomp($P); + + if ($P eq '1') { + open A, "/sys/class/power_supply/BAT0/energy_full"; + my $full_charge = ; + close A; + chomp($full_charge); + + open A, "/sys/class/power_supply/BAT0/energy_now"; + my $current_charge = ; + close A; + chomp($current_charge); + + $str .= sprintf(" | Bat: %03d%% ", int(($current_charge / $full_charge) * 100) ); + undef $current_charge; undef $full_charge; + } + } + + return $str; +} + +sub getbatterychargestr2() { + my $str .= " | Power: "; + open AC,"/sys/class/power_supply/ADP1/online"; + + if ( == 1) { + $str .= "AC"; + } else { + $str .= "DC"; + } + + close AC; # display % charge only if possible + + if (open DC,"/sys/class/power_supply/BAT0/capacity") { + $str .= ' '. ; + close DC; + chomp $str; + $str .= '%'; + } + + return $str; +} + +sub getbatterychargestr3() { + my $capacity = $properties->Get('org.freedesktop.UPower.Device', 'Percentage'); + my $state = $properties->Get('org.freedesktop.UPower.Device', 'State'); + my $time = "?"; + + if ($state == 2) { +# discharging + $time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToEmpty'); + # time in seconds, let's translate it to hours:minutes + $state = '▼'; + } elsif ($state == 1) { +# charging + $time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToFull'); + $state = '▲'; + } else { +# already charged + $time = 0; + $state = '•'; + } + + $time = to_hours ($time); + + return sprintf(" | %s%% %s %s", $capacity, $state, $time); +} + +sub getlangstr() { + my $str .= " | Lang: "; + + if (`xset -q` =~ /Group 2: on /o) { + $str .= "RU"; + } else { + $str .= "EN"; + } + + return $str; +} + +sub meminfo() { + if (defined($MEMINFOHANDLE)) { + open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1); + } else { + open ($MEMINFOHANDLE, "/proc/meminfo"); + } + + my @mem = <$MEMINFOHANDLE>; + seek $MEMINFOHANDLE, SEEK_SET, 0; + + @mem = map { substr($_, 0, -4) } @mem; + + my $memavail = (split(/\s+/, $mem[2]))[1]; + my $swaptotal = (split(/\s+/, $mem[14]))[1]; + my $swapfree = (split(/\s+/, $mem[15]))[1]; + + return sprintf ( + " | mem: %s M | sw: %s M", + int($memavail / 1024), + int(($swaptotal - $swapfree) / 1024) + ); +} + +sub to_hours ($) { + my $sec = shift; + my $hrs = $sec / (60 * 60); + $hrs = 0 if ( $hrs < 1 ); + my $min = ($sec - ($hrs * 60 * 60)) / 60; + $min = 0 if ( $min < 1 ); + return sprintf("%02d:%02d", $hrs, $min); +}