Skip to content

Instantly share code, notes, and snippets.

@xtetsuji
Created April 18, 2014 18:01
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
Battery watcher and observer for Mac and Linux laptop.
#!/usr/bin/env perl
# xtetsuji by 2014/04/19
our $VERSION = "0.01";
use strict;
use warnings;
use utf8;
use AnyEvent;
use Config;
#use Cocoa::Growl ':all';
use File::Basename qw(basename);
use Getopt::Long ();
use WebService::ImKayac::Simple;
use constant HAVE_COCOA_GROWL => eval {
require Cocoa::Growl;
import Cocoa::Growl ':all';
1;
};
if ( !HAVE_COCOA_GROWL ) {
# Cocoa::Growl の無い環境ではとりあえず何もしないコマンドとして定義しておく
*growl_register = sub {};
*growl_notify = sub {};
}
use constant APPLICATION_NAME => basename($0);
use constant GRAPH_DOWN => -1;
use constant GRAPH_UP => 1;
use constant GRAPH_RELAX => 0;
use constant OSNAME => $Config{osname};
my $p = Getopt::Long::Parser->new(
config => [qw(posix_default no_ignore_case auto_help)]
);
$p->getoptions(
'watch-percents=s' => \my $watch_percents,
'imkayac-config=s' => \my $imkayac_config,
'interval=i' => \my $interval,
);
our $DEFAULT_INTERVAL = 600;
growl_register(
app => APPLICATION_NAME,
#icon => '',
notifications => [qw/info/],
);
my $IMKAYAC_CONFIG_FILE = $imkayac_config || "$ENV{HOME}/.imkayac.yml";
if ( !-f $IMKAYAC_CONFIG_FILE ) {
die qq(ImKayac config file "$IMKAYAC_CONFIG_FILE" is not found\n);
}
binmode STDOUT, ':utf8';
my @watch_percents = (20, 50, 80);
if ( $watch_percents ) {
@watch_percents = split /,/, $watch_percents;
if ( grep { !/^\d+$/ } @watch_percents ) {
die "watch-percent option specify comma separated digits.\n";
}
}
#chomp(my $hostname = `hostname`);
my $hostname = $Config{myhostname};
my $previous_percent = get_remaining(); # initialize
my $cv = AnyEvent->condvar;
my $im = WebService::ImKayac::Simple->new($IMKAYAC_CONFIG_FILE);
my $notify_callback = sub {
my $response = shift;
print $response . "\n"; # DEBUG?
growl_notify(
name => 'info',
title => APPLICATION_NAME,
description => $response,
);
$im->send(APPLICATION_NAME . ": " . $response . " ($hostname)"); # ok either flagged utf-8 or not.
};
my $timer = AnyEvent->timer(
after => 10,
interval => $interval || $DEFAULT_INTERVAL,
cb => sub {
my $current_percent = get_remaining();
my $response = '';
# process...
for my $key (@watch_percents) {
if ( my $res = graph_direction( $previous_percent => $current_percent, $key ) ) {
if ( $res == GRAPH_UP ) {
$response = "${key}% を上回りました。現在${current_percent}%です。";
}
elsif ( $res == GRAPH_DOWN ) {
$response = "${key}% を下回りました。現在${current_percent}%です。";
}
}
}
if ( $previous_percent != 100 && $current_percent == 100 ) {
$response = "満充電されました。";
}
if ( $response ) {
$notify_callback->($response);
}
# reinitialize
$previous_percent = $current_percent;
},
);
$cv->recv();
sub get_remaining {
if ( OSNAME eq 'darwin' ) {
return get_remaining_mac()
} elsif ( OSNAME eq 'linux' ) {
return get_remaining_linux();
} else {
die "Unsupported your architecture yet\nPlease contact to \@xtetsuji by Twitter if you want to use this program!\n";
}
}
sub get_remaining_mac {
my $pmset = `pmset -g ps`;
my ($percent) = $pmset =~ /(\d+)%; /;
return $percent;
}
# 追加してみたけどまだ試していない
sub get_remaining_linux {
my $acpi = `acpi -b`;
my ($percent) = $acpi =~ /(\d+)%, /;
return $percent;
}
# see: http://polamjag.hatenablog.jp/entry/2013/10/23/125843
sub graph_direction {
my ($prev, $cur, $thr) = @_;
if ( grep { !/^\d+$/ } ($prev, $cur, $thr) ) {
require Carp;
Carp::croak "graph_direction error. ($prev, $cur, $thr)";
}
if ( $cur < $thr && $thr < $prev ) {
return GRAPH_DOWN;
}
elsif ( $prev < $thr && $thr < $cur ) {
return GRAPH_UP;
}
else {
return GRAPH_RELAX;
}
}
=pod
=head1 NAME
battery-watchd - battery watcher and observer for Mac and Linux laptop
=head1 SYNOPSIS
battery-watchd &
=head1 OPTIONS
=head2 --watch-percents
battery-watchd --watch-percents=5,10,15,20
Specify watch percents separated by comma.
=head2 --imkayac-config
battery-watchd --imkayac-config=/path/to/config.yml
Specify your ImKayac config file path.
Default path is "$ENV{HOME}/.imkayac.yml".
This file format is YAML format. See below CONFIG FILE SYNTAX section.
=head2 --interval
battery-watchd --interval=600
Specify watching interval seconds.
Default may be 600 seconds. You confirm it by following command.
grep DEFAULT_INTERAVAL `which battery-watched`
=head1 CONFIG FILE SYNTAX
You can give a battery state by ImKayac.
So you have to tell this program ImKayac setting.
This program gives ImKayac setting file of YAML file.
It syntax is same as L<WebService::ImKayac::Simle>'s format.
Setting file's path is below "--imkayac-config" section.
=head1 DEPENDENCIES
L<AnyEvent>,
L<Cocoa::Growl>,
L<WebService::ImKayac::Simple>,
and some Perl5 core modules.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2014 by OGATA Tetsuji
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment