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);
+}