1

Compare commits

...

43 Commits

Author SHA1 Message Date
eleksir
dc58f0c6a9 i3status-anyevent moved to separate repo - i3status-ae 2021-06-19 14:15:41 +03:00
eleksir
044acbf148 i3status-anyevent: on vpn state file check mtime, not atime (it was typo) 2021-03-15 23:50:17 +03:00
eleksir
b36eaf7e40 acpid.pl: cleanup, use vars for fh instead of bare words, fix fd leak on battery status file 2021-03-13 17:48:05 +03:00
eleksir
04fdac8891 i3status-anyevent: fix incorrect vpn status file mtime check 2021-03-13 17:25:43 +03:00
Sergei Fedosov
035afae865 i3status-anyevent: Add cron plugin 2021-02-25 18:50:25 +03:00
Sergei Fedosov
58d896c597 i3status-anyevent: i3status-anyevent %SIG should be local 2021-02-25 16:56:57 +03:00
Sergei Fedosov
d1fcd2b8a4 i3status-anyevent: Add left|right click cmd for clock plugin 2021-02-24 18:06:10 +03:00
eleksir
27904b8d50 i3status-anyevent: Fix caps indicator, at last 2021-02-21 18:12:49 +03:00
eleksir
7d4e8dccb4 i3status-anyevent: Add simple net if state indicator 2021-02-21 17:56:26 +03:00
eleksir
0d2453623c i3status-anyevent: Actually check if simple-volume-pa enabled 2021-02-21 16:58:22 +03:00
eleksir
139b014f7b i3status-anyevent: Make tcp connect check only if vpn state check enabled 2021-02-21 16:54:00 +03:00
eleksir
7a270291b1 i3status-anyevent: if we cannot spawn - silently giveup 2021-02-21 16:40:14 +03:00
eleksir
b287c84eed i3status-anyevent: i3 uses xdg std for config dir path, so we too 2021-02-21 16:35:09 +03:00
eleksir
02bb1399fb i3status-anyevent: fix capslock indicator border color 2021-02-21 12:51:45 +03:00
eleksir
8fc99eeb50 i3status-anyevent: Add simplified volume indicator, make charge flash sign bigger 2021-02-21 12:49:46 +03:00
eleksir
fbb3fbdb07 i3status-anyevent: there are other files in /sys for battery on kernel 4.4.x and thinkpad 2021-02-20 22:06:06 +03:00
Sergei Fedosov
ccf477bc65 i3status-anyevent: move cpu mon file location, color and background color to config 2021-02-20 20:28:42 +03:00
Sergei Fedosov
217a86ecff i3status-anyevent: run app from button only on left-click 2021-02-20 19:50:11 +03:00
Sergei Fedosov
3a09fcf22f i3status-anyevent: upower does not provide "time to" value if battery fully chrged 2021-02-20 18:36:09 +03:00
Sergei Fedosov
1cb4103dd6 i3status-anyevent: change battery backend, fix restart i3bar issues, rename conf
* Rename config.json to i3status-anyevent.json, old name still supported
* Drop dbus and use upower directly with option use /sys poll instead
* Use setsid() to prevent windows get stoned when i3bar restarted (and
* status scrept re-launched)
* Do not use syswrite on utf8 filehandles, it's deprecated
* Move some settings to config
* Add lots of comments to config
2021-02-20 17:49:23 +03:00
Sergei Fedosov
bb41416926 i3status-anyevent: unless hiding declaration of $FH 2021-02-20 12:24:45 +03:00
Sergei Fedosov
4452e2fe0f i3status-anyevent: highlight app "buttons" with active windows, code style fixes 2021-02-19 19:32:28 +03:00
Sergei Fedosov
20789b2a2c i3status-anyevent: add ability to reload config, relaxed json parser 2021-02-18 19:08:41 +03:00
eleksir
949ce2f0c7 Refactor, modernize i3status-timers.json-io 2021-02-13 19:44:46 +03:00
Sergei Fedosov
96fc306ef7 Add i3status-anyevent 2021-02-13 19:43:10 +03:00
Sergei Fedosov
a102651d7a tpingd.go: Add laptop battery query via dbus 2020-10-14 19:41:02 +03:00
Sergei Fedosov
4fbb5170d2 tpingd.go: do not use net/http 2020-10-02 14:41:51 +03:00
Sergei Fedosov
169f4ef309 Add tpingd.go - tcp pinger 2020-09-29 09:35:09 +03:00
eleksir
b6d1722b25 i3status-timers.json-io: remap stdio to /dev/null on spawn() 2020-03-15 21:08:08 +03:00
eleksir
0324616c01 Add touchpad_toggle 2020-03-15 21:04:40 +03:00
eleksir
0cbe1eb7a0 i3status-timers.json-io: make output more gently, suppress errors on unsucessful spawn 2020-03-15 17:12:08 +03:00
eleksir
1687579c16 Add MIT License 2020-03-15 15:56:41 +03:00
eleksir
cad1f400df i3status-timers.json-io: use external config for buttons 2020-03-15 15:06:18 +03:00
eleksir
4724fd9533 i3status-timers, i3status-timers: tinker a bit 2020-03-10 00:40:11 +03:00
eleksir
156d67e3fd Add draft of i3status-timers.json-io 2020-03-10 00:38:37 +03:00
eleksir
4ad2b845d4 Add i3status-timers.json-o 2020-03-10 00:38:04 +03:00
eleksir
d88d4a552a xbacklight: fix incorrect path, add comment 2020-03-08 14:52:00 +03:00
eleksir
4c04356810 i3status-timers*: tinker a bit cpuspeed stat 2020-03-08 14:43:39 +03:00
eleksir
6dab9c5d8e i3status-timers: facelift it according i3status-timers.dbus 2020-03-08 14:33:39 +03:00
eleksir
d349fbd0f2 i3status-timers.dbus: Do not close file handles where possible 2020-03-08 14:32:46 +03:00
eleksir
c59a66022a i3status-timers.dbus: use uttf8, add more info
* Add capslock status
* Add wlan0 status and ipaddr
* Add cputemp
* Add/stash cpu cores speed (more work required to represent  it in compact mode)
* More compact meminfo
* Remove uptime, no usecase for desktop
* Remove focused window string sub
* Remove current locale indicator (xxkb shows it)
* remove cron wrapper subs
* Remove outdated comments
* Remove alternative battery charge detection subs
2020-03-08 07:12:52 +03:00
eleksir
f80c9be5aa i3status-timers: cleanup, make less cpu-intensive 2020-02-25 23:58:57 +03:00
eleksir
46c893be36 Add i3status-timers.dbus 2020-02-25 22:49:09 +03:00
9 changed files with 1946 additions and 234 deletions

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright (C) 2020 Sergei Fedosoff
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

114
acpid.pl
View File

@@ -2,15 +2,10 @@
#
# Hibernates system if battery charge drops under $MIN_CHARGE and battery discharging
use strict;
use warnings "all";
use Fcntl;
sub logger($); # logs messages if $debug != 0
# maybe one time i'll use it
sub i3wmstate; # returns 1 if i3wm running, else - 0
use warnings;
sub logger; # logs messages if $debug != 0
$0 = 'acpid.pl';
my $debug = 0;
@@ -18,8 +13,8 @@ my $MIN_CHARGE = 10;
my $base = '/sys/class/power_supply/BAT0';
unless(-f "$base/present") {
logger("Battery info at /sys/class/BAT0/present not found, quitting.\n");
unless (-f "$base/present") {
logger "Battery info at /sys/class/BAT0/present not found, quitting.";
exit 0;
}
@@ -27,90 +22,89 @@ my $battery_present = 2;
my $battery_check = 2;
my $charging = 2;
while ( sleep(180) ) {
# check that battery is in place
open(ACPI, "$base/present") or next;
my $buf = '';
while (sleep 180) {
open (my $batteryFH, '<', "$base/present") or next;
my $buf;
if (read(ACPI, $buf, 1)) {
if (read ($batteryFH, $buf, 1)) {
if ($battery_check == 0) {
logger("Ability to read from /sys/class/BAT0/present restored\n");
logger "Ability to read from $base/present restored";
$battery_check = 1;
}
if ($buf == '0') {
if ($battery_present != 0) {
logger("We have no battery, skipping charge level polling until it appears\n");
if ($battery_present) {
logger "We have no battery, skipping charge level polling until it appears";
$battery_present = 0;
}
close ACPI;
close $batteryFH;
next;
}
} else {
if ($battery_check != 0) {
logger("Unable to read from /sys/class/BAT0/present\n");
if ($battery_check) {
logger "Unable to read from /sys/class/BAT0/present";
$battery_check = 0;
}
close ACPI;
close $batteryFH;
next;
}
close ACPI;
close $batteryFH;
$battery_present = 1;
# check status, we have no need to poll battery if it charging/charged
unless (-f "$base/status") {
logger("Something broken in /sys, unable to find $base/status, quitting\n");
logger "Something broken in /sys, unable to find $base/status, quitting";
exit 1;
}
# TODO: file access save state and print on change
open(STATUS, "$base/status") or do {
logger("Unable to open $base/status\n");
open (my $statusFH, '<', "$base/status") or do {
logger "Unable to open $base/status";
next;
};
$buf = <STATUS>;
close STATUS;
chomp($buf);
$buf = <$statusFH>;
close $statusFH;
chomp $buf;
if ($buf ne 'Discharging') {
if ($charging != 1) {
logger("Battery charging.\n");
logger "Battery charging.";
$charging = 1;
}
} else {
if ($charging != 0) {
logger("Battery discharging.\n");
if ($charging) {
logger "Battery discharging.";
$charging = 0;
}
}
# read charge state
unless (-f "$base/capacity") {
logger("Something broken in /sys, unable to find $base/capacity, quitting\n");
logger "Something broken in /sys, unable to find $base/capacity, quitting";
exit 1;
}
# TODO: file access save state and print on change
open(CHARGE, "$base/capacity") or do {
open (my $chargeFH, '<', "$base/capacity") or do {
logger("Unable to open $base/capacity\n");
next;
};
read(CHARGE, $buf, 3) or do {
logger("Unable to read $base/capacity, but file is in place\n");
read ($chargeFH, $buf, 3) or do {
logger "Unable to read $base/capacity, but file is in place";
next;
};
chomp($buf); # just in case
close $chargeFH;
chomp $buf; # just in case
if ($buf < $MIN_CHARGE) {
if ($charging != 0) { # discharging
logger("Battery charge is less than 10%, hibernating\n");
logger "Battery charge is less than 10%, hibernating";
`dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate`;
}
} else {
@@ -122,51 +116,15 @@ while ( sleep(180) ) {
`notify-send --urgency=normal --expire-time=3000 "Battery overcharging"`;
}
logger("Charge is $buf%\n");
logger "Charge is $buf%";
}
}
sub logger ($) {
if ($debug != 0) {
sub logger {
if ($debug) {
my $msg = shift;
$msg = localtime() . ' ' . $msg;
$msg = sprintf '%s %s\n', localtime (), $msg;
syswrite STDOUT, $msg;
}
}
sub i3wmstate {
my $flag = 0;
opendir(P, '/proc') || die 'no /proc found!';
while (readdir(P)) {
my $pid = $_;
next unless(defined($pid));
next if ($pid eq '');
if (-d "/proc/$pid") {
# dir UID == APCID.pl process user owner
if ((stat("/proc/$pid"))[4] == int(getpwnam($ENV{'LOGNAME'}))) {
next unless(-r "/proc/$pid/cmdline");
open(CMDLINE, "/proc/$pid/cmdline") || die "unable to open /proc/$pid/cmdline";
my $cl = <CMDLINE>;
close(CMDLINE);
if(defined($cl)) {
if ((substr($cl, 0, 2) eq 'i3') and (length($cl) <= 4)) {
$flag = 1;
undef $cl;
undef $pid;
last;
}
}
undef $cl;
}
}
undef $pid;
}
return $flag;
}

View File

@@ -1,40 +1,24 @@
#!/usr/bin/perl
# vim: set ai noet ts=8 sw=8 sts=8 ft=perl :
# vim: set ai noet ts=4 sw=4 sts=4 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 5.10.0;
use utf8;
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 meminfo();
sub ifaces();
sub cpuspeed();
sub cputemp();
sub caps();
sub caps_find();
my $slow_timer = 360; # 0.333 * 360 ~= 2 min
@@ -47,35 +31,68 @@ my $pstr = '';
my $charge;
my $la;
my $uptime;
my $time;
my $mem;
my $net;
my $cpuspeed;
my $cputemp;
my $LAHANDLE;
my $MEMINFOHANDLE;
my $CPUTEMPHANDLE;
my %CPUSCALEHANDLE;
my %CPUSCALEMAXHANDLE;
my $ROUTEHANDLE;
my %IFSTATEHANDLE;
my $CAPSHANDLE;
my $ACHANDLE;
my $DCHANDLE;
my $CAPSPATH;
my @IFACE = qw (wlan0);
my %IFSTATE;
my %IFPSTATE;
my %IFADDR;
my $ACFILE;
if ( -f "/sys/class/power_supply/ADP1/online") {
$ACFILE = "/sys/class/power_supply/ADP1/online";
} elsif ("/sys/class/power_supply/AC/online") {
$ACFILE = "/sys/class/power_supply/AC/online";
}
sleep 1;
while (1) {
if ($onesec_timer >= 3) {
onesec_cron();
# $cpuspeed = cpuspeed();
$cputemp = cputemp();
$time = gettimestr();
# as we report time with precision of 1 minute, update 1/60 seconds
$mem = meminfo();
$net = ifaces();
$onesec_timer = 0;
}
if ($slow_timer >= 360) {
slow_cron();
$charge = getbatterychargestr2();
$la = getlastr();
$CAPSPATH = caps_find() unless (defined($CAPSPATH));
$slow_timer = 0;
}
$str = '';
# $str .= getfocusedwidowtitlestr();
# $str .= "$ENV{'USER'}";
$str .= getlangstr();
$str .= $uptime;
# my $str = $cpuspeed;
my $str = caps();
$str .= $net;
$str .= $cputemp;
$str .= $la;
$str .= $mem;
$str .= $charge;
$str .= $time;
utf8::encode($str);
if ($pstr ne $str) {
syswrite STDOUT, "$str\n";
say $str;
$pstr = $str;
}
@@ -87,19 +104,6 @@ while (1) {
select(undef, undef, undef, 0.333);
}
sub slow_cron() {
$charge = getbatterychargestr2();
$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;
@@ -108,130 +112,271 @@ sub gettimestr() {
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() {
open UPTIME, "/proc/uptime" if (tell(UPTIME) == -1);
$u = <UPTIME>;
seek UPTIME, SEEK_SET, 0;
$u = (split(/ /, $u, 2))[0];
$days = int($u / 86400); # 86400 = 1 day
$hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour
$minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60);
$seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes));
my $str = sprintf(" | up: %sd,%02sh,%02sm ", $days, $hours, $minutes);
return $str;
}
sub getlastr() {
open LA, "/proc/loadavg" if (tell(LA) == -1);
if (defined($LAHANDLE)) {
open ($LAHANDLE, "/proc/loadavg") if (tell($LAHANDLE) == -1);
} else {
open ($LAHANDLE, "/proc/loadavg");
}
my $la = <LA>;
seek LA, SEEK_SET, 0;
my $la = readline($LAHANDLE);
seek $LAHANDLE, SEEK_SET, 0;
$la = (split(/ /, $la, 2))[0];
return (" | LA: $la ");
}
sub getbatterychargestr1() {
sub getbatterychargestr2() {
my $str .= " | ⚡ ";
if (defined($ACHANDLE)) {
open ($ACHANDLE, $ACFILE) if (tell($ACHANDLE) == -1);
} else {
open ($ACHANDLE, $ACFILE);
}
if (readline($ACHANDLE) == 1) {
$str .= "AC";
} else {
$str .= "DC";
}
seek $ACHANDLE, SEEK_SET, 0;
if (defined($DCHANDLE)) {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity") if (tell($DCHANDLE) == -1);
} else {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity");
}
$str .= " " . readline($DCHANDLE);
chomp($str);
$str .= '%';
seek $DCHANDLE, SEEK_SET, 0;
return $str;
}
sub meminfo() {
if (defined($MEMINFOHANDLE)) {
open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1);
} else {
open ($MEMINFOHANDLE, "/proc/meminfo");
}
my @mem;
while ( ! eof($MEMINFOHANDLE) ) {
push @mem, readline($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/sw: %s/%s M",
int($memavail / 1024),
int(($swaptotal - $swapfree) / 1024)
);
}
sub ifaces() {
my $str = '';
if (-f "/sys/class/power_supply/BAT0/present") {
open A, "/sys/class/power_supply/BAT0/present";
$P = <A>;
close A;
chomp($P);
foreach my $if (@IFACE) {
my $addr = "no addr";
my $link;
if ($P eq '1') {
open A, "/sys/class/power_supply/BAT0/energy_full";
my $full_charge = <A>;
close A;
chomp($full_charge);
if (defined($IFSTATEHANDLE{$if})) {
if (tell($IFSTATEHANDLE{$if}) == -1) {
unless (open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate")) {
$str .= " | ? $if: not exist";
next;
}
}
} else {
open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate") or do {
$str .= " | ? $if: not exist";
next;
};
}
open A, "/sys/class/power_supply/BAT0/energy_now";
my $current_charge = <A>;
close A;
chomp($current_charge);
$IFSTATE{$if} = readline($IFSTATEHANDLE{$if});
seek $IFSTATEHANDLE{$if}, SEEK_SET, 0;
$IFPSTATE{$if} = $IFSTATE{$if} unless(defined($IFPSTATE{$if}));
$str .= sprintf(" | Bat: %03d%% ", int(($current_charge / $full_charge) * 100) );
undef $current_charge; undef $full_charge;
if ($IFSTATE{$if} eq "up\n") {
$link = '▲';
} else {
$link = '▼';
}
if ($IFPSTATE{$if} ne $IFSTATE{$if}) {
$IFADDR{$if} = undef;
$IFPSTATE{$if} = $IFSTATE{$if}
}
unless (defined($IFADDR{$if})) {
if (defined($ROUTEHANDLE)) {
open ($ROUTEHANDLE, "/proc/self/net/route") if (tell($ROUTEHANDLE) == -1);
} else {
open ($ROUTEHANDLE, "/proc/self/net/route");
}
my @route;
while ( ! eof($ROUTEHANDLE)) {
push @route, readline($ROUTEHANDLE);
}
seek $ROUTEHANDLE, SEEK_SET, 0;
foreach my $r (@route) {
if ((split(/\t/, $r, 2))[0] eq $if) {
$addr = (split(/\n/, `/sbin/ip address show dev $if`))[2];
$addr =~ m/ inet (.+)\//;
$IFADDR{$if} = $1;
last;
}
}
}
unless (defined($IFADDR{$if})) {
$str .= sprintf(" | %s %s: %s", $link, $if, $addr);
} else {
$str .= sprintf(" | %s %s: %s", $link, $if, $IFADDR{$if});
}
}
return $str;
}
sub getbatterychargestr2() {
my $str .= " | Power: ";
open AC,"/sys/class/power_supply/ADP1/online";
sub cpuspeed() {
my $str = 'cpu:';
if (<AC> == 1) {
$str .= "AC";
opendir(C, "/sys/devices/system/cpu/cpufreq") or do {
return '';
};
while (readdir(C)) {
next if($_ eq '.');
next if($_ eq '..');
if (defined($CPUSCALEHANDLE{$_})) {
if (tell($CPUSCALEHANDLE{$_}) == -1) {
unless (open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq")) {
return '';
}
}
} else {
open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq") or do {
return '';
};
}
my $speed = readline($CPUSCALEHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speed;
$speed = int($speed / 1000);
if (defined($CPUSCALEMAXHANDLE{$_})) {
if (tell($CPUSCALEMAXHANDLE{$_}) == -1) {
unless (open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq")) {
return '';
}
}
} else {
open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq") or do {
return '';
};
}
my $speedmax = readline($CPUSCALEMAXHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speedmax;
$speedmax = int($speedmax / 1000);
$str .= sprintf(" %s/%s", $speed, $speedmax);
}
closedir C;
return $str . " MHz";
}
sub cputemp() {
if (defined($CPUTEMPHANDLE)) {
if (tell($CPUTEMPHANDLE) == -1) {
unless (open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input")) {
return '';
}
}
} else {
$str .= "DC";
open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input") or do {
return '';
};
}
close AC; # display % charge only if possible
my $t = readline($CPUTEMPHANDLE);
seek $CPUTEMPHANDLE, SEEK_SET, 0;
chomp $t;
$t = int($t);
$t = int($t / 1000) if ($t > 1000);
if (open DC,"/sys/class/power_supply/BAT0/capacity") {
$str .= ' '. <DC>;
close DC;
chomp $str;
$str .= '%';
return sprintf(" | %s°", $t);
}
sub caps() {
if (defined($CAPSPATH)) {
if (defined($CAPSHANDLE)) {
if (tell($CAPSHANDLE) == -1) {
unless (open($CAPSHANDLE, $CAPSPATH)) {
$CAPSPATH = undef;
return "? caps";
}
}
} else {
open($CAPSHANDLE, $CAPSPATH) or do {
$CAPSPATH = undef;
return "? caps";
};
}
my $state = readline($CAPSHANDLE);
seek $CAPSHANDLE, SEEK_SET, 0;
chomp $state;
if ($state eq '1') {
return '☒ caps';
} else {
return '☐ caps';
}
}
}
sub caps_find() {
my $str;
opendir (C, "/sys/class/input");
my $cnt = 0;
while (readdir(C)) {
if (-f sprintf("/sys/class/input/%s/input0::capslock/brightness", $_)) {
$str = sprintf("/sys/class/input/%s/input0::capslock/brightness", $_);
last;
}
if (-f sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt)) {
$str = sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt);
last;
}
$cnt++;
}
closedir C;
return $str;
}
sub getlangstr() {
my $str .= " | Lang: ";
if (`xset -q` =~ /Group 2: on /o) {
$str .= "RU";
} else {
$str .= "EN";
}
return $str;
}
sub meminfo() {
open (M, "/proc/meminfo");
my @mem = <M>;
close M;
@mem = map { substr($_, 0, -4) } @mem;
my $memavail = (split(/\s+/, @mem[2]))[1];
my $swaptotal = (split(/\s+/, @mem[15]))[1];
my $swapfree = (split(/\s+/, @mem[16]))[1];
return sprintf (
" | mem: %s M | sw: %s M",
int($memavail / 1024),
int(($swaptotal - $swapfree) / 1024)
);
}

388
i3status-timers.dbus Normal file
View File

@@ -0,0 +1,388 @@
#!/usr/bin/perl
# vim: set ai noet ts=4 sw=4 sts=4 ft=perl :
# TODO: check for file descriptor leak for used fd munching technique
use strict;
use warnings "all";
use Fcntl qw(:seek);
use Net::DBus;
use 5.10.0;
use utf8;
binmode STDOUT;
binmode STDERR;
sub gettimestr();
sub getlastr();
sub getbatterychargestr3();
sub to_hours($);
sub meminfo();
sub ifaces();
sub cpuspeed();
sub cputemp();
sub caps();
sub caps_find();
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 $time;
my $mem;
my $net;
my $cpuspeed;
my $cputemp;
# prep dee-boos connection
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");
# find out caps lock indicator
my $CAPSPATH = &caps_find();
my $LAHANDLE;
my $MEMINFOHANDLE;
my $CPUTEMPHANDLE;
my %CPUSCALEHANDLE;
my %CPUSCALEMAXHANDLE;
my $ROUTEHANDLE;
my %IFSTATEHANDLE;
my $CAPSHANDLE;
my @IFACE = qw (wlan0);
my %IFSTATE;
my %IFPSTATE;
my %IFADDR;
# take a nap
sleep 1;
while (1) {
if ($onesec_timer >= 3) {
# $cpuspeed = cpuspeed();
$cputemp = cputemp();
$time = gettimestr();
$mem = meminfo();
$net = ifaces();
$onesec_timer = 0;
}
if ($slow_timer >= 360) {
$charge = getbatterychargestr3();
$la = getlastr();
$CAPSPATH = caps_find() unless (defined($CAPSPATH));
$slow_timer = 0;
}
# my $str = $cpuspeed;
my $str = caps();
$str .= $net;
$str .= $cputemp;
$str .= $la;
$str .= $mem;
$str .= $charge;
$str .= $time;
utf8::encode($str);
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 gettimestr() {
my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6];
$year = $year + 1900;
return sprintf(" | %s, %s %s %s %02s:%02s ", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min);
}
sub getlastr() {
if (defined($LAHANDLE)) {
open $LAHANDLE, "/proc/loadavg" if (tell($LAHANDLE) == -1);
} else {
open $LAHANDLE, "/proc/loadavg";
}
my $str = readline($LAHANDLE);
seek $LAHANDLE, SEEK_SET, 0;
$str = (split(/ /, $str, 2))[0];
return " | LA: $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) unless ($time eq '?');
return sprintf(" | ⚡ %s%% %s %s", $capacity, $state, $time);
}
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);
}
sub meminfo() {
if (defined($MEMINFOHANDLE)) {
open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1);
} else {
open ($MEMINFOHANDLE, "/proc/meminfo");
}
my @mem;
while ( ! eof($MEMINFOHANDLE) ) {
push @mem, readline($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/sw: %s/%s M",
int($memavail / 1024),
int(($swaptotal - $swapfree) / 1024)
);
}
sub ifaces() {
my $str = '';
foreach my $if (@IFACE) {
my $addr = "no addr";
my $link;
if (defined($IFSTATEHANDLE{$if})) {
if (tell($IFSTATEHANDLE{$if}) == -1) {
unless (open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate")) {
$str .= " | ? $if: not exist";
next;
}
}
} else {
open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate") or do {
$str .= " | ? $if: not exist";
next;
};
}
$IFSTATE{$if} = readline($IFSTATEHANDLE{$if});
seek $IFSTATEHANDLE{$if}, SEEK_SET, 0;
$IFPSTATE{$if} = $IFSTATE{$if} unless(defined($IFPSTATE{$if}));
if ($IFSTATE{$if} eq "up\n") {
$link = '▲';
} else {
$link = '▼';
}
if ($IFPSTATE{$if} ne $IFSTATE{$if}) {
$IFADDR{$if} = undef;
$IFPSTATE{$if} = $IFSTATE{$if}
}
unless (defined($IFADDR{$if})) {
if (defined($ROUTEHANDLE)) {
open ($ROUTEHANDLE, "/proc/self/net/route") if (tell($ROUTEHANDLE) == -1);
} else {
open ($ROUTEHANDLE, "/proc/self/net/route");
}
my @route;
while ( ! eof($ROUTEHANDLE)) {
push @route, readline($ROUTEHANDLE);
}
seek $ROUTEHANDLE, SEEK_SET, 0;
foreach my $r (@route) {
if ((split(/\t/, $r, 2))[0] eq $if) {
$addr = (split(/\n/, `/sbin/ip address show dev $if`))[2];
$addr =~ m/ inet (.+)\//;
$IFADDR{$if} = $1;
last;
}
}
}
unless (defined($IFADDR{$if})) {
$str .= sprintf(" | %s %s: %s", $link, $if, $addr);
} else {
$str .= sprintf(" | %s %s: %s", $link, $if, $IFADDR{$if});
}
}
return $str;
}
sub cpuspeed() {
my $str = 'cpu:';
opendir(C, "/sys/devices/system/cpu/cpufreq") or do {
return '';
};
while (readdir(C)) {
next if($_ eq '.');
next if($_ eq '..');
if (defined($CPUSCALEHANDLE{$_})) {
if (tell($CPUSCALEHANDLE{$_}) == -1) {
unless (open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq")) {
return '';
}
}
} else {
open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq") or do {
return '';
};
}
my $speed = readline($CPUSCALEHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speed;
$speed = int($speed / 1000);
if (defined($CPUSCALEMAXHANDLE{$_})) {
if (tell($CPUSCALEMAXHANDLE{$_}) == -1) {
unless (open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq")) {
return '';
}
}
} else {
open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq") or do {
return '';
};
}
my $speedmax = readline($CPUSCALEMAXHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speedmax;
$speedmax = int($speedmax / 1000);
$str .= sprintf(" %s/%s", $speed, $speedmax);
}
closedir C;
return $str . " MHz";
}
sub cputemp() {
if (defined($CPUTEMPHANDLE)) {
if (tell($CPUTEMPHANDLE) == -1) {
unless (open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input")) {
return '';
}
}
} else {
open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input") or do {
return '';
};
}
my $t = readline($CPUTEMPHANDLE);
seek $CPUTEMPHANDLE, SEEK_SET, 0;
chomp $t;
$t = int($t);
$t = int($t / 1000) if ($t > 1000);
return sprintf(" | %s°", $t);
}
sub caps() {
if (defined($CAPSPATH)) {
if (defined($CAPSHANDLE)) {
if (tell($CAPSHANDLE) == -1) {
unless (open($CAPSHANDLE, $CAPSPATH)) {
$CAPSPATH = undef;
return "? caps";
}
}
} else {
open($CAPSHANDLE, $CAPSPATH) or do {
$CAPSPATH = undef;
return "? caps";
};
}
my $state = readline($CAPSHANDLE);
seek $CAPSHANDLE, SEEK_SET, 0;
chomp $state;
if ($state eq '1') {
return '☒ caps';
} else {
return '☐ caps';
}
}
}
sub caps_find() {
my $str;
opendir (C, "/sys/class/input");
my $cnt = 0;
while (readdir(C)) {
if (-f sprintf("/sys/class/input/%s/input0::capslock/brightness", $_)) {
$str = sprintf("/sys/class/input/%s/input0::capslock/brightness", $_);
last;
}
if (-f sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt)) {
$str = sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt);
last;
}
$cnt++;
}
closedir C;
return $str;
}

600
i3status-timers.json-io Normal file
View File

@@ -0,0 +1,600 @@
#!/usr/bin/perl
# vim: set ai noet ts=4 sw=4 sts=4 ft=perl :
use utf8;
use open qw (:std :utf8);
use strict;
use warnings;
use Carp qw (confess);
use Data::Dumper;
use Fcntl qw(:seek :mode :DEFAULT);
use 5.22.2;
use JSON::XS;
use Net::DBus;
use POSIX qw (setsid);
use threads;
sub input_thread();
sub readconf();
sub gettimestr();
sub getlastr();
sub getbatterychargestr2();
sub getbatterychargestr3();
sub to_hours ($);
sub meminfo();
sub ifaces();
sub cpuspeed();
sub cputemp();
sub caps();
sub caps_find();
sub spawn(@);
binmode STDIN;
binmode STDERR;
binmode STDOUT;
my $read = 0;
$SIG{__DIE__} = \&Carp::confess;;
$SIG{"CONT"} = sub { $read = 1 };
$SIG{"STOP"} = sub { $read = 0 };
$SIG{"PIPE"} = sub { warn "SIGPIPE" };
$SIG{"HUP"} = sub { warn "SIGHUP" };
$SIG{"USR1"} = sub { warn "SIGUSR1" };
$SIG{"WINCH"} = sub { warn "SIGWINCH" };
my $slow_timer = 360; # 0.333 * 360 ~= 2 min
my $onesec_timer = 3; # 0.333 * 3 ~= 1 sec
# read config
my ($C, %CMD) = readconf();
my $buttonsamount = @{$C};
my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек');
my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб');
my $tmp = '';
my $charge = '';
my $la = '';
my $time = '';
my $mem = '';
my $net = '';
my $cpuspeed = '';
my $cputemp = '';
my $caps = '';
# file handles :)
my $LAHANDLE;
my $MEMINFOHANDLE;
my $CPUTEMPHANDLE;
my %CPUSCALEHANDLE;
my %CPUSCALEMAXHANDLE;
my $ROUTEHANDLE;
my %IFSTATEHANDLE;
my $CAPSHANDLE;
my $ACHANDLE;
my $DCHANDLE;
# global vars
my $CAPSPATH;
my @IFACE = qw (wlan0);
my %IFSTATE;
my %IFPSTATE;
my %IFADDR;
my $ACFILE;
# main json 'object';
my $ji; # input
my $jo; # output
# output changed flag;
my $jf = 1; # if true - we should ot show json
if ( -f "/sys/class/power_supply/ADP1/online") {
$ACFILE = "/sys/class/power_supply/ADP1/online";
} elsif ("/sys/class/power_supply/AC/online") {
$ACFILE = "/sys/class/power_supply/AC/online";
}
# prep dee-boos connection
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");
threads->create('input_thread')->detach();
# capture click events and do not override sigstop and sigcont numbers
syswrite STDOUT, '{"version": 1, "click_events": true}
[ [],
';
sleep 1;
while (1) {
# json message that will be spewed to i3bar
my $je;
if ($onesec_timer >= 3) {
# $cpuspeed = cpuspeed();
$tmp = cputemp();
if ($cputemp ne $tmp) {
$jf = 1;
$cputemp = $tmp;
}
$tmp = gettimestr();
if ($time ne $tmp) {
$jf = 1;
$time = $tmp;
}
$tmp = meminfo();
if ($mem ne $tmp) {
$jf = 1;
$mem = $tmp;
}
$tmp = ifaces();
if ($net ne $tmp) {
$jf = 1;
$net = $tmp;
}
$onesec_timer = 0;
}
if ($slow_timer >= 360) {
$tmp = getbatterychargestr3();
if ($charge ne $tmp) {
$jf = 1;
$charge = $tmp;
}
$tmp = getlastr();
if ($la ne $tmp) {
$jf = 1;
$la = $tmp;
}
$CAPSPATH = caps_find() unless (defined($CAPSPATH));
$slow_timer = 0;
}
$tmp = caps();
if ($caps ne $tmp) {
$jf = 1;
$caps = $tmp;
}
if ($jf) {
$jo->[0]->{full_text} = $time;
$jo->[0]->{color} = '#3e78fd';
$jo->[1]->{full_text} = $charge;
$jo->[1]->{color} = '#3e78fd';
$jo->[2]->{full_text} = $mem;
$jo->[2]->{color} = '#3e78fd';
$jo->[3]->{full_text} = $la;
$jo->[3]->{color} = '#3e78fd';
$jo->[4]->{full_text} = $cputemp;
$jo->[4]->{color} = '#3e78fd';
$jo->[5]->{full_text} = $net;
$jo->[5]->{color} = '#3e78fd';
$jo->[6]->{full_text} = $caps;
$jo->[6]->{color} = '#3e78fd';
@{$je} = (@{$jo}, @{$C});
@{$je} = reverse(@{$je});
my $output = eval { encode_json($je); };
if ($output) {
syswrite STDOUT, $output . ",\n";
}
$jf = 0;
}
# tick timers
$slow_timer++;
$onesec_timer++;
# sleep for 0.333 second;
select(undef, undef, undef, 0.333);
}
sub readconf() {
open (my $CONF, '<:encoding(UTF-8)', "$ENV{HOME}/.i3/config.json") or die "Unable to open $ENV{HOME}/.i3/config.json: $!\n";
my $len = (stat "$ENV{HOME}/.i3/config.json")[7];
use bytes;
read ($CONF, my $c, $len) or die "unable to read $ENV{HOME}/.i3/config.json";
no bytes;
close $CONF;
$c = eval { decode_json ($c); };
if ($@) {
die "Unable to decode $ENV{HOME}/.i3/config.json: $@\n";
}
my ($j, %cmd);
my $cnt = 0;
foreach (@{$c}) {
$j->[$cnt]->{full_text} = $_->{full_text} // 'no fucken name';
$j->[$cnt]->{name} = $_->{name} // $_->{full_text};
$j->[$cnt]->{instance} = $_->{instance} // $_->{full_text};
$j->[$cnt]->{color} = $_->{color} // '#00aa33';
$cmd{$_->{name}} = $_->{cmd} // '/usr/bin/true';
$cnt++
}
return ($j, %cmd);
}
sub input_thread() {
# on input of this script i3bar sends infinite json array
# one special thing about it: all elements of this array presented as
# text string ended wth new line, so we can omit first string and parse
# elements as independed json messages, but we have to strip leading ","
readline(*STDIN); # throw away leading "[\n"
my $char;
while (1) {
my $msg = eval { readline(*STDIN) };
next unless ($msg);
$msg = substr($msg, 1) if (substr($msg, 0, 1) eq ','); # drop leading ',' if present
my $j = decode_json($msg);
if (defined($CMD{$j->{name}})) {
spawn($CMD{$j->{name}});
}
}
}
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 getlastr() {
if (defined($LAHANDLE)) {
open ($LAHANDLE, "/proc/loadavg") if (tell($LAHANDLE) == -1);
} else {
open ($LAHANDLE, "/proc/loadavg");
}
my $la = readline($LAHANDLE);
seek $LAHANDLE, SEEK_SET, 0;
$la = (split(/ /, $la, 2))[0];
return ("LA: $la");
}
sub getbatterychargestr2() {
my $str .= "⚡ ";
if (defined($ACHANDLE)) {
open ($ACHANDLE, $ACFILE) if (tell($ACHANDLE) == -1);
} else {
open ($ACHANDLE, $ACFILE);
}
if (readline($ACHANDLE) == 1) {
$str .= "AC";
} else {
$str .= "DC";
}
seek $ACHANDLE, SEEK_SET, 0;
if (defined($DCHANDLE)) {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity") if (tell($DCHANDLE) == -1);
} else {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity");
}
$str .= " " . readline($DCHANDLE);
chomp($str);
$str .= '%';
seek $DCHANDLE, SEEK_SET, 0;
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) unless ($time eq '?');
return sprintf("⚡ %s%% %s %s", $capacity, $state, $time);
}
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);
}
sub meminfo() {
if (defined($MEMINFOHANDLE)) {
open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1);
} else {
open ($MEMINFOHANDLE, "/proc/meminfo");
}
my @mem;
while ( ! eof($MEMINFOHANDLE) ) {
push @mem, readline($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/sw: %s/%s M",
int($memavail / 1024),
int(($swaptotal - $swapfree) / 1024)
);
}
sub ifaces() {
my $str = '';
foreach my $if (@IFACE) {
my $addr = "no addr";
my $link;
if (defined($IFSTATEHANDLE{$if})) {
if (tell($IFSTATEHANDLE{$if}) == -1) {
unless (open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate")) {
$str .= "? $if: not exist";
next;
}
}
} else {
open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate") or do {
$str .= "? $if: not exist";
next;
};
}
$IFSTATE{$if} = readline($IFSTATEHANDLE{$if});
seek $IFSTATEHANDLE{$if}, SEEK_SET, 0;
$IFPSTATE{$if} = $IFSTATE{$if} unless(defined($IFPSTATE{$if}));
if ($IFSTATE{$if} eq "up\n") {
$link = '▲';
} else {
$link = '▼';
}
if ($IFPSTATE{$if} ne $IFSTATE{$if}) {
$IFADDR{$if} = undef;
$IFPSTATE{$if} = $IFSTATE{$if}
}
unless (defined($IFADDR{$if})) {
if (defined($ROUTEHANDLE)) {
open ($ROUTEHANDLE, "/proc/self/net/route") if (tell($ROUTEHANDLE) == -1);
} else {
open ($ROUTEHANDLE, "/proc/self/net/route");
}
my @route;
while ( ! eof($ROUTEHANDLE)) {
push @route, readline($ROUTEHANDLE);
}
seek $ROUTEHANDLE, SEEK_SET, 0;
foreach my $r (@route) {
if ((split(/\t/, $r, 2))[0] eq $if) {
$addr = (split(/\n/, `/sbin/ip address show dev $if`))[2];
$addr =~ m/ inet (.+)\//;
$IFADDR{$if} = $1;
last;
}
}
}
unless (defined($IFADDR{$if})) {
$str .= sprintf("%s %s: %s", $link, $if, $addr);
} else {
$str .= sprintf("%s %s: %s", $link, $if, $IFADDR{$if});
}
}
return $str;
}
sub cpuspeed() {
my $str = 'cpu:';
opendir(C, "/sys/devices/system/cpu/cpufreq") or do {
return '';
};
while (readdir(C)) {
next if($_ eq '.');
next if($_ eq '..');
if (defined($CPUSCALEHANDLE{$_})) {
if (tell($CPUSCALEHANDLE{$_}) == -1) {
unless (open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq")) {
return '';
}
}
} else {
open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq") or do {
return '';
};
}
my $speed = readline($CPUSCALEHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speed;
$speed = int($speed / 1000);
if (defined($CPUSCALEMAXHANDLE{$_})) {
if (tell($CPUSCALEMAXHANDLE{$_}) == -1) {
unless (open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq")) {
return '';
}
}
} else {
open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq") or do {
return '';
};
}
my $speedmax = readline($CPUSCALEMAXHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speedmax;
$speedmax = int($speedmax / 1000);
$str .= sprintf(" %s/%s", $speed, $speedmax);
}
closedir C;
return $str . " MHz";
}
sub cputemp() {
if (defined($CPUTEMPHANDLE)) {
if (tell($CPUTEMPHANDLE) == -1) {
unless (open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input")) {
return '';
}
}
} else {
open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input") or do {
return '';
};
}
my $t = readline($CPUTEMPHANDLE);
seek $CPUTEMPHANDLE, SEEK_SET, 0;
chomp $t;
$t = int($t);
$t = int($t / 1000) if ($t > 1000);
return sprintf("%s°", $t);
}
sub caps() {
if (defined($CAPSPATH)) {
if (defined($CAPSHANDLE)) {
if (tell($CAPSHANDLE) == -1) {
unless (open($CAPSHANDLE, $CAPSPATH)) {
$CAPSPATH = undef;
return "? caps";
}
}
} else {
open($CAPSHANDLE, $CAPSPATH) or do {
$CAPSPATH = undef;
return "? caps";
};
}
my $state = readline($CAPSHANDLE);
seek $CAPSHANDLE, SEEK_SET, 0;
chomp $state;
if ($state eq '1') {
return '☒ caps';
} else {
return '☐ caps';
}
}
}
sub caps_find() {
my $str;
opendir (C, "/sys/class/input");
my $cnt = 0;
while (readdir(C)) {
if (-f sprintf("/sys/class/input/%s/input0::capslock/brightness", $_)) {
$str = sprintf("/sys/class/input/%s/input0::capslock/brightness", $_);
last;
}
if (-f sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt)) {
$str = sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt);
last;
}
$cnt++;
}
closedir C;
return $str;
}
sub spawn (@) {
my @args = @_;
my $pid = fork();
if ($pid) { # Parent
return;
} elsif ($pid == 0) { # Child
POSIX::setsid ();
# we need no io streams here, right?
# it seems that at least vscode creashes if we close stdio handles
open(STDOUT, ">", "/dev/null");
open(STDERR, ">", "/dev/null");
open(STDIN, "<", "/dev/null");
$pid = fork ();
if ($pid) { # Parent
# in this place parent quits
exit 0;
} elsif ($pid == 0) { # Child
my $prg = shift(@args);
# weird situation, silently quit here :)
exit 0 unless(defined($prg));
if (@args > 0) {
exec $prg @args;
} else {
exec $prg;
}
} else { # Unable to fork()
syswrite STDERR, "[{\"full_text\":\"ERROR: Could not fork new process: $!\",\"color\":\"#ff0000\"}],\n";
}
} else { # Unable to fork()
syswrite STDERR, "[{\"full_text\":\"ERROR: Could not fork new process: $!\",\"color\":\"#ff0000\"}],\n";
}
}

435
i3status-timers.json-o Normal file
View File

@@ -0,0 +1,435 @@
#!/usr/bin/perl
# vim: set ai noet ts=4 sw=4 sts=4 ft=perl :
use strict;
use warnings "all";
use Fcntl qw(:seek);
use 5.10.0;
use utf8;
use JSON::XS;
binmode STDOUT;
binmode STDERR;
sub gettimestr();
sub getlastr();
sub getbatterychargestr2();
sub meminfo();
sub ifaces();
sub cpuspeed();
sub cputemp();
sub caps();
sub caps_find();
my $slow_timer = 360; # 0.333 * 360 ~= 2 min
my $onesec_timer = 3; # 0.333 * 3 ~= 1 sec
my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек');
my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб');
my $tmp = '';
my $charge = '';
my $la = '';
my $time = '';
my $mem = '';
my $net = '';
my $cpuspeed = '';
my $cputemp = '';
my $caps = '';
# file handles :)
my $LAHANDLE;
my $MEMINFOHANDLE;
my $CPUTEMPHANDLE;
my %CPUSCALEHANDLE;
my %CPUSCALEMAXHANDLE;
my $ROUTEHANDLE;
my %IFSTATEHANDLE;
my $CAPSHANDLE;
my $ACHANDLE;
my $DCHANDLE;
# global vars
my $CAPSPATH;
my @IFACE = qw (wlan0);
my %IFSTATE;
my %IFPSTATE;
my %IFADDR;
my $ACFILE;
# main json 'object';
my $ji; # input
my $jo; # output
# output changed flag;
my $jf = 1; # if true - we should ot show json
if ( -f "/sys/class/power_supply/ADP1/online") {
$ACFILE = "/sys/class/power_supply/ADP1/online";
} elsif ("/sys/class/power_supply/AC/online") {
$ACFILE = "/sys/class/power_supply/AC/online";
}
sleep 1;
syswrite STDOUT, '{"version":1}
[ [],
';
while (1) {
if ($onesec_timer >= 3) {
# $cpuspeed = cpuspeed();
$tmp = cputemp();
if ($cputemp ne $tmp) {
$jf = 1;
$cputemp = $tmp;
}
$tmp = gettimestr();
if ($time ne $tmp) {
$jf = 1;
$time = $tmp;
}
$tmp = meminfo();
if ($mem ne $tmp) {
$jf = 1;
$mem = $tmp;
}
$tmp = ifaces();
if ($net ne $tmp) {
$jf = 1;
$net = $tmp;
}
$onesec_timer = 0;
}
if ($slow_timer >= 360) {
$tmp = getbatterychargestr2();
if ($charge ne $tmp) {
$jf = 1;
$charge = $tmp;
}
$tmp = getlastr();
if ($la ne $tmp) {
$jf = 1;
$la = $tmp;
}
$CAPSPATH = caps_find() unless (defined($CAPSPATH));
$slow_timer = 0;
}
$tmp = caps();
if ($caps ne $tmp) {
$jf = 1;
$caps = $tmp;
}
if ($jf) {
$jo->[0]->{full_text} = $caps;
$jo->[0]->{color} = '#3e78fd';
$jo->[1]->{full_text} = $net;
$jo->[1]->{color} = '#3e78fd';
$jo->[1]->{full_text} = $cputemp;
$jo->[1]->{color} = '#3e78fd';
$jo->[2]->{full_text} = $la;
$jo->[2]->{color} = '#3e78fd';
$jo->[3]->{full_text} = $mem;
$jo->[3]->{color} = '#3e78fd';
$jo->[4]->{full_text} = $charge;
$jo->[4]->{color} = '#3e78fd';
$jo->[5]->{full_text} = $time;
$jo->[5]->{color} = '#3e78fd';
syswrite STDOUT, encode_json($jo) . ",\n";
$jf = 0;
}
# tick timers
$slow_timer++;
$onesec_timer++;
# sleep for 0.333 second;
select(undef, undef, undef, 0.333);
}
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 getlastr() {
if (defined($LAHANDLE)) {
open ($LAHANDLE, "/proc/loadavg") if (tell($LAHANDLE) == -1);
} else {
open ($LAHANDLE, "/proc/loadavg");
}
my $la = readline($LAHANDLE);
seek $LAHANDLE, SEEK_SET, 0;
$la = (split(/ /, $la, 2))[0];
return ("LA: $la");
}
sub getbatterychargestr2() {
my $str .= "⚡ ";
if (defined($ACHANDLE)) {
open ($ACHANDLE, $ACFILE) if (tell($ACHANDLE) == -1);
} else {
open ($ACHANDLE, $ACFILE);
}
if (readline($ACHANDLE) == 1) {
$str .= "AC";
} else {
$str .= "DC";
}
seek $ACHANDLE, SEEK_SET, 0;
if (defined($DCHANDLE)) {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity") if (tell($DCHANDLE) == -1);
} else {
open ($DCHANDLE, "/sys/class/power_supply/BAT0/capacity");
}
$str .= " " . readline($DCHANDLE);
chomp($str);
$str .= '%';
seek $DCHANDLE, SEEK_SET, 0;
return $str;
}
sub meminfo() {
if (defined($MEMINFOHANDLE)) {
open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1);
} else {
open ($MEMINFOHANDLE, "/proc/meminfo");
}
my @mem;
while ( ! eof($MEMINFOHANDLE) ) {
push @mem, readline($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/sw: %s/%s M",
int($memavail / 1024),
int(($swaptotal - $swapfree) / 1024)
);
}
sub ifaces() {
my $str = '';
foreach my $if (@IFACE) {
my $addr = "no addr";
my $link;
if (defined($IFSTATEHANDLE{$if})) {
if (tell($IFSTATEHANDLE{$if}) == -1) {
unless (open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate")) {
$str .= "? $if: not exist";
next;
}
}
} else {
open ($IFSTATEHANDLE{$if}, "/sys/class/net/$if/operstate") or do {
$str .= "? $if: not exist";
next;
};
}
$IFSTATE{$if} = readline($IFSTATEHANDLE{$if});
seek $IFSTATEHANDLE{$if}, SEEK_SET, 0;
$IFPSTATE{$if} = $IFSTATE{$if} unless(defined($IFPSTATE{$if}));
if ($IFSTATE{$if} eq "up\n") {
$link = '▲';
} else {
$link = '▼';
}
if ($IFPSTATE{$if} ne $IFSTATE{$if}) {
$IFADDR{$if} = undef;
$IFPSTATE{$if} = $IFSTATE{$if}
}
unless (defined($IFADDR{$if})) {
if (defined($ROUTEHANDLE)) {
open ($ROUTEHANDLE, "/proc/self/net/route") if (tell($ROUTEHANDLE) == -1);
} else {
open ($ROUTEHANDLE, "/proc/self/net/route");
}
my @route;
while ( ! eof($ROUTEHANDLE)) {
push @route, readline($ROUTEHANDLE);
}
seek $ROUTEHANDLE, SEEK_SET, 0;
foreach my $r (@route) {
if ((split(/\t/, $r, 2))[0] eq $if) {
$addr = (split(/\n/, `/sbin/ip address show dev $if`))[2];
$addr =~ m/ inet (.+)\//;
$IFADDR{$if} = $1;
last;
}
}
}
unless (defined($IFADDR{$if})) {
$str .= sprintf("%s %s: %s", $link, $if, $addr);
} else {
$str .= sprintf("%s %s: %s", $link, $if, $IFADDR{$if});
}
}
return $str;
}
sub cpuspeed() {
my $str = 'cpu:';
opendir(C, "/sys/devices/system/cpu/cpufreq") or do {
return '';
};
while (readdir(C)) {
next if($_ eq '.');
next if($_ eq '..');
if (defined($CPUSCALEHANDLE{$_})) {
if (tell($CPUSCALEHANDLE{$_}) == -1) {
unless (open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq")) {
return '';
}
}
} else {
open ($CPUSCALEHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_cur_freq") or do {
return '';
};
}
my $speed = readline($CPUSCALEHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speed;
$speed = int($speed / 1000);
if (defined($CPUSCALEMAXHANDLE{$_})) {
if (tell($CPUSCALEMAXHANDLE{$_}) == -1) {
unless (open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq")) {
return '';
}
}
} else {
open ($CPUSCALEMAXHANDLE{$_}, "/sys/devices/system/cpu/cpufreq/$_/scaling_max_freq") or do {
return '';
};
}
my $speedmax = readline($CPUSCALEMAXHANDLE{$_});
seek $CPUSCALEHANDLE{$_}, SEEK_SET, 0;
chomp $speedmax;
$speedmax = int($speedmax / 1000);
$str .= sprintf(" %s/%s", $speed, $speedmax);
}
closedir C;
return $str . " MHz";
}
sub cputemp() {
if (defined($CPUTEMPHANDLE)) {
if (tell($CPUTEMPHANDLE) == -1) {
unless (open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input")) {
return '';
}
}
} else {
open ($CPUTEMPHANDLE, "/sys/class/hwmon/hwmon0/temp1_input") or do {
return '';
};
}
my $t = readline($CPUTEMPHANDLE);
seek $CPUTEMPHANDLE, SEEK_SET, 0;
chomp $t;
$t = int($t);
$t = int($t / 1000) if ($t > 1000);
return sprintf("%s°", $t);
}
sub caps() {
if (defined($CAPSPATH)) {
if (defined($CAPSHANDLE)) {
if (tell($CAPSHANDLE) == -1) {
unless (open($CAPSHANDLE, $CAPSPATH)) {
$CAPSPATH = undef;
return "? caps";
}
}
} else {
open($CAPSHANDLE, $CAPSPATH) or do {
$CAPSPATH = undef;
return "? caps";
};
}
my $state = readline($CAPSHANDLE);
seek $CAPSHANDLE, SEEK_SET, 0;
chomp $state;
if ($state eq '1') {
return '☒ caps';
} else {
return '☐ caps';
}
}
}
sub caps_find() {
my $str;
opendir (C, "/sys/class/input");
my $cnt = 0;
while (readdir(C)) {
if (-f sprintf("/sys/class/input/%s/input0::capslock/brightness", $_)) {
$str = sprintf("/sys/class/input/%s/input0::capslock/brightness", $_);
last;
}
if (-f sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt)) {
$str = sprintf("/sys/class/input/%s/input%s::capslock/brightness", $_, $cnt);
last;
}
$cnt++;
}
closedir C;
return $str;
}

8
touchpad_toggle Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
if [[ $(xinput list 12|grep -c "This device is disabled") == "1" ]]; then
xinput enable 12
else
xinput disable 12
fi

149
tpingd.go Normal file
View File

@@ -0,0 +1,149 @@
package main
import (
"fmt"
"net"
"os"
"time"
"github.com/godbus/dbus/v5"
)
var pingres = false
var sleeptime time.Duration = 5
var charge = "[??% ? 00:00]"
func secondsToClock(inSeconds int64) string {
hours := (inSeconds / 60) / 60
minutes := inSeconds % 60
str := fmt.Sprintf("%02d:%02d", hours, minutes)
return str
}
func mycharge () {
for true {
conn, err := dbus.SystemBus()
if err != nil {
time.Sleep(sleeptime * time.Second)
continue
}
defer conn.Close()
obj := conn.Object("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/battery_BAT0")
percentage, err := obj.GetProperty("org.freedesktop.UPower.Percentage")
if err != nil {
conn.Close()
time.Sleep(sleeptime * time.Second)
continue
}
var pcharge int = int(percentage.Value().(float64))
state, err := obj.GetProperty("org.freedesktop.UPower.State")
if err != nil {
conn.Close()
time.Sleep(sleeptime * time.Second)
continue
}
var status string = "?"
var chtime string = "00:00"
if state.Value().(uint32) == 1 {
mytime, err := obj.GetProperty("org.freedesktop.UPower.TimeToFull")
if err != nil {
chtime = "00:00"
} else {
var seconds = mytime.Value().(int64)
chtime = secondsToClock(seconds)
}
status = "▲"
} else if state.Value().(uint32) == 2 {
mytime, err := obj.GetProperty("org.freedesktop.UPower.TimeToEmpty")
if err != nil {
chtime = "00:00"
} else {
var seconds = mytime.Value().(int64)
chtime = secondsToClock(seconds)
}
status = "▼"
} else if state.Value().(uint32) == 4 {
status = "•"
}
charge = fmt.Sprintf("[%02d%% %s %s]\n", pcharge, status, chtime)
time.Sleep(sleeptime * time.Second)
}
}
func myping() {
for true {
conn, e := net.DialTimeout("tcp", "jenkins:443", 3000 * time.Millisecond)
if e != nil {
pingres = false
} else {
conn.Close()
pingres = true
}
time.Sleep(sleeptime * time.Second)
}
}
func handleConnection(conn net.Conn) {
buf := make([]byte, 1024)
bufLen, err := conn.Read(buf)
if err == nil {
tail := string(buf[bufLen - 4 : bufLen])
// ah, fuck, yea. if you check buffer with \n\r\n\r against "\n\r\n\r" you'll get always FALSE, but if check against hex values, it works
if bufLen > 4 && fmt.Sprintf("%x", tail) == "0d0a0d0a" {
if pingres {
var answer = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: text/plain\nConnection: close\n\nReachable %s\n", charge)
conn.Write([]byte(answer))
} else {
var answer = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: text/plain\nConnection: close\n\nUnreachable %s\n", charge)
conn.Write([]byte(answer))
}
conn.Close()
} else {
conn.Write([]byte("HTTP/1.1 400 Bad Request\nContent-Type: text/plain\nConnection: close\n\nBad Request\n"))
conn.Close()
}
}
}
func main() {
ln, e := net.Listen("tcp", "127.0.0.1:9000")
if e != nil {
fmt.Println(e)
os.Exit(1)
}
go myping()
go mycharge()
for {
// infinitely handle incomming connections
conn, e := ln.Accept()
if e != nil {
// shit happens, let's try one more time
continue
}
go handleConnection(conn)
}
}

View File

@@ -1,4 +1,10 @@
#!/usr/bin/perl
#
# TODO: check intel' backlight path too if generic is not found
# this script should have suid bit set and must have root owner :(
use strict;
use warnings "all";
my $arg = $ARGV[0];
my $step = 10; # measured in percents
@@ -6,12 +12,15 @@ my $step = 10; # measured in percents
sub fsread($); # read 1-st line from file
sub fswrite(@); # write string to file
my $brightnessfile = "/sys/class/backlight/acpi_video0/brightness";
my $maxbrightness = fsread("/sys/class/backlight/acpi_video0/max_brightness");
my $currbrightness = fsread($brightnessfile);
#my $prefix = "/sys/class/backlight/acpi_video0";
my $prefix = "/sys/class/backlight/intel_backlight";
my $a = $maxbrightness / 100;
$step = int($step * $a);
my $brightnessfile = "$prefix/brightness";
my $maxbrightness = fsread("$prefix/max_brightness");
my $currbrightness = fsread("$prefix/brightness");
my $p = $maxbrightness / 100;
$step = int($step * $p);
if ( $arg eq "up" ) {
if ($currbrightness != $maxbrightness) {
@@ -38,7 +47,7 @@ if ( $arg eq "up" ) {
sub fsread($) {
my $fname = shift;
open (F, $fname) || die;
open (F, $fname) || die "Unable to read $fname: $!\n";
my $str = <F>;
close F;
return $str;
@@ -47,7 +56,7 @@ sub fsread($) {
sub fswrite (@) {
my $str = shift;
my $fname = shift;
open(OF, ">", $fname) || die;
open(OF, ">", $fname) || die "Unable to write $fname: $!\n";
print OF $str;
close OF;
}