読者です 読者をやめる 読者になる 読者になる

部屋を掃除したら漫画が沢山出てきたので書く日記

漫画とか合唱とかUNIXとかLinuxとかについて書く日記です。

朝測定した体重をはてなグラフにメール投稿する

はじめに

「はてなグラフ」という、値を入力するとグラフを表示してくれるサービスがあり、このブログの左側に「退社時間」という「はてなグラフ」で作ったグラフを表示させています。
しかし値の入力を「はてなグラフ」の入力画面に毎日アクセスして入力するのが面倒で、そのうち止めてしまっていました。

そして最近、体重が増えてまいっちんぐな状況なので、ダイエットを行い、かつ毎朝体重を計ってグラフにしようと考え、またはてなグラフを利用することにしました。しかし入力が面倒になっては退社時間グラフの二の舞です。「あー、はてなグラフに携帯からメール送って値を投稿できれば良いのになー」と思って調べてみたら、なんと大分前からはてなグラフはAPIが公開されていたのでした
APIとはプログラミングをする際に、サービスを利用する事が出来る仕組みを指します。はてなグラフを運営しているはてなという会社ははてなグラフをプログラムから操作する仕組み、APIを提供してくれている訳です。これを使えばプログラム経由ではてなグラフを更新することが出来そうです。サンプルプログラムも、慣れ親しんでいるperlで書かれているのも素敵です。さらに応用して、以下のような事が出来そうだと考えました。

  1. 家で体重を計る
  2. 計った体重を携帯からメールで所定のメールアドレスに送る
  3. メールに書かれた体重を読み取り、APIを利用してはてなグラフに入力する
  4. はてなグラフ「朝一に計った体重」が更新される

ちなみにグラフはこんな感じです。
朝一に計った体重(Kg)


という訳でperlのプログラム「hatenagraph.pl」を用いた、朝一に計った体重をはてなグラフにメールで投稿するシステムを作ってみました。動作は以下の通りです。

システムのおおまかな動作(基本設計)

1. 人力で行う処理

1-1.朝起きたら自宅で体重を測定する
1-2.測定した体重を、携帯からメールで所定のメールアドレスへ送信する。メールの書式は
Subject(件名)を

bataweight [体重]
例:
bataweight 67.5

とする。

2.プログラム「hatenagraph.pl」が行う処理

2-1.所定メールボックスPOP3でアクセスし、一番最近届いたメールの件名をチェックする。
2-2.件名が「myweight [体重]」だったら、体重の値を記録し、メールをメールボックス削除、POP3接続を終了する。
件名が違ったら、その次に新しいメールの件名をチェックする。以下繰り返し。
2-3. 記録した体重の値を、はてなグラフ「朝一に計った体重」のプログラムを実行した日の値として登録する。

3. サーバが行う処理

3-1.10分おきにhatenagraph.plを実行する。

システムの詳しい情報(詳細設計)

hatenagraph.plの内容

上記はてなグラフAPIのサンプルプログラムや、こちらで紹介されているperlPOP3アクセスを行うためのプログラムを参考に(ていうかほぼそのままです・・・)、以下のプログラムを作りました。

#!/usr/bin/perl

use strict;
use warnings;
use DateTime;
use LWP::UserAgent;
use Net::POP3;

#チェックする文字列
my $KEYWORD = 'bataweight';

#POP接続用情報
my $popuser = 'xxxx'; #POPログインID
my $poppass = 'xxxx'; #POPログインパスワード
my $popserver = 'xxxx'; #pop3サーバ名
my $popport = xxxx; #pop3ポート番号

#はてなログイン情報
my $hatenauser = 'bata64'; #はてなログインID
my $hatenapass = 'xxxx'; #はてなログインパスワード
my $hatenagraphname = '朝一に計った体重(Kg)'; #はてなグラフのグラフ名(utf-8)

#プロキシ情報
my $use_proxy = 0; #proxyを使用するかどうか。1で使用、0で使用しない
my $proxy = 'http://example.com:28080'; #httpプロキシサーバのホスト名:ポート番号(http://から記入)

#変数定義
my $maildata = 0;
my $weight = 0;
my $counter = 0;
my @array = ();

#POPサーバ接続処理
##POP接続開始
my $pop = Net::POP3->new($popserver, Port => $popport);
if ( ! $pop ){
        die "接続失敗: $!";
}
print "###POP connect###","\n";

##POPログイン
$pop->user($popuser);
print "###POP user###","\n";
my $pop_check = $pop->pass($poppass);
print "###POP pass###","\n";

##POP認証チェック
if ( ! defined $pop_check ){
        die "認証失敗: ";

##メールボックス内の通数が0の場合はPOP接続終了
} elsif ( $pop_check == 0 ){
        ##POP接続終了
        $pop->quit();
print "###POP quit because NOT MESSAGES###","\n";
}

while ( $pop_check > 0 ){
        my $msg = $pop->get($pop_check);
print "###POP retr $pop_check###","\n";
        foreach ( @$msg ){
                if ( $_ =~ /^Subject: $KEYWORD/){
print "###match bataweight!###","\n";
                        $maildata = $_;
                        $counter += 1;
                        $pop->delete($pop_check);
                        last;
                }
        }

        if ( $counter == 1){
                last;
        }
        $pop_check -= 1;
}

##POP接続終了
$pop->quit();

##体重を取得
chomp($maildata);
@array = split(/ /, $maildata);

$weight = $array[2];

if ( ! $weight == 0 ){
        print "###hatena###","\n";
        #はてなグラフへの接続処理
        my $ua = LWP::UserAgent->new;

        ##プロキシ設定
        if ( $use_proxy == 1 ){
                $ua->proxy([qw(http https)] => $proxy);
        }

        ##API経由ではてなグラフへ接続
        $ua->credentials('graph.hatena.ne.jp:80', '', $hatenauser, $hatenapass);
        my $res = $ua->post( 'http://graph.hatena.ne.jp/api/post', {
                graphname => $hatenagraphname,
                date => DateTime->now( time_zone=>'local' )->ymd,
                value => $weight
        });
        warn $res->content unless $res->code == 201;
}
exit
プログラムが動作する場所

プログラムが動作するには、「cronやperlを実行できてインターネットに接続していて24時間365日稼働しているLinuxまたはUNIXサーバ」が必要と考えましたが、自宅の機器でやるには色々大変なので、さくらインターネットのレンタルサーバを使うことにしました。月額500円で上記条件を満たす、FreeBSDというUNIX OSがインストールされたサーバを借りられます。

なお、さくらのレンタルサーバperl(v5.8.9)には、上記プログラムで使ったperlモジュールが全てインストール済みでした。ローカル環境にCPANモジュールインストールするのにチャレンジしなきゃいかんかと思っていたので助かりました。メンテが行き届いているように感じられ好印象です。

こちらのサーバに、以下のディレクトリパスで実行権を付与したプログラムのファイルを格納しました。

/home/bata64/pl/hatenagraph.pl
10分おきにプログラムを実行する仕組み

10分おきにプログラムを実行するのは人力だと辛いので、仕事で親しんでいるUNIXLinuxでおなじみの「cron」を使う事にしました。cronを使うと決まった時間に所定のプログラムを実行させることが出来ます。cronについての細かい説明は省きますが、以下のように設定しました。

*/10    *       *       *       0,1,2,3,4,5,6   /home/bata64/pl/hatenagraph.pl

まとめ

朝一で計った体重をメールで送ってグラフ化したい、というのが目的でしたが、この仕組みを使えば更新を止めていた退社時間グラフも楽に更新が出来そうです。凄いことは何一つやっていませんが作っていて自分が楽しかったので良しとします。
また、パソコンと接続できる体重計(知りませんがそういうのあるんですかね)があれば、体重計ってグラフ作成までを全て自動化できるのではないかと思います。

なお、作成中に会社の同期諸氏から「グラフ生成APIならgoogleにもあるよ」とか「cloudforecastとかのイマドキな機構使った方が便利だよ」とか言われましたが、とりあえず思いついた機能をどんな手段でも実現させるのが今回の目的だったので、良いのです!今後のアップデートの際に参考にさせていただきたいと思います。

あと、上記のシステムは色々改善の余地がありますのでもう少し手を加えたいと思います。思いついているのは以下のような事柄です。

  • 同期O氏に「実行時にログ吐かせるだろjk」と言われたので実行時にログを出力するようにする
  • メールのチェック条件はSubjectヘッダだけで良いのか?Dateヘッダもチェックすると本日以外の日のデータを投稿できるようになるのではないか。
  • Subjectが日本語含まれていても、iso-2022-jpエンコード後の文字列でマッチさせればいいやー、と思ったら、メールクライアント毎にエンコードの仕方が違う模様(少なくとも自宅秀丸メールと携帯からとでは違った)なのでうまくマッチされなかった。とりあえず半角英数字だけ使う事にする。
  • 投稿したいグラフをWEBページから設定できたりすると便利かもなー。
  • rubyで書いてみる

では。