Category Archives: PERSONAL COMPUTER - Page 2

Raspberry Piを使ってスマホ・音声で家電を制御するシステムを作ってみた

最近、スマホ制御や音声制御できる家電が話題になっているで低価格かつ比較的簡単に構築できるか試してみました。

iRemoconなど便利な製品も出ているのに何故自作かといいますと。。。
失礼ながらこの製品がお高いのと、将来的な機能拡張を考えると圧倒的に自作に分があると考えたからです。

簡単な解説動画を制作してみました

達成目標

  • スマホ等からリモートで操作できること
  • 音声だけで何も触れずに操作できること
  • なるべく低価格で構築すること
  • なるべく単純なスクリプトで実装すること
  • 自宅サーバを構築しているような感覚で構築できること

ハードウエア

  1. Raspberry Pi Type B
  2. USB接続 赤外線リモコンキット
  3. GW-USValue-EZ(無線LAN子機)
  4. TEMPer V23.5(温度計)
  5. MM-MCUSB21BK(マイク)
  6. MS-UP201BK(スピーカー)
  7. U2H-EG4SWH(セルフパワーのUSBハブ)
  8. その他、USB延長コードなど

※ USB接続 赤外線リモコンキットを使用するのは、事前の実験にてLIRCではエアコンなどの長い命令を送る家電の制御が出来ないことがあると判明したためです。

簡単な仕組みについての図
学習リモコン
※ 図ではマイクがハブへの接続になってますが、ノイズが酷い場合はRaspberry Piへ直挿しの方がいいです。

Raspberry Piの初期設定

Raspberry PiのOSインストールに関しては以前まとめたものがありますのでこちらを御覧ください。

有線LANでも構築できますが、どうしても無線LANを使用したい場合、設定はネットに多くの情報が出ておりますので各自で調べるようお願いします。

USB接続された機器の制御で必要となるパッケージのインストール
$ sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libusb-dev

USB接続 赤外線リモコンキット制御用コマンドのインストール
$ git clone https://github.com/kjmkznr/bto_ir_cmd.git
$ cd bto_ir_cmd/
$ make
$ sudo mv bto_ir_cmd /usr/local/bin/

信号を受信する場合は次のように実行します。
$ sudo bto_ir_cmd -e -r

信号を送信する場合は次のように実行します。
$ sudo bto_ir_cmd -e -t 0000000000000000000000000000000000000000000000000000000000000000000000
※ 00000….の部分は受信した時に表示されたものを使用します。

TEMPer V23.5制御用コマンドのインストール
$ git clone https://github.com/bitplane/temper.git
$ cd temper/
$ vi temper.c

                /* 44行目付近の行で日付がグリニッジ標準時となってるので修正 */
                //utc = gmtime(&t);
                utc = localtime(&t);

                /* 47行目付近の行で日付のフォーマットが欧米仕様となってるので修正 */
                //strftime(dt, 80, "%d-%b-%Y %H:%M", utc);
                strftime(dt, 80, "%Y-%m-%d %H:%M:%S", utc);

$ make
$ sudo make install

温度を取得する場合は次のように実行します。
$ sudo temper

WEBリモコン機能の実装

ネットワーク図
性質上、直接外部に公開すると明らかに色々と問題があるシステムなので公開しないで運用出来るようにしました。
ネットワーク図
※ 図ではルータのVPN機能を使用していますが、Raspberry PiにVPNを構築して接続するのも良いかもしれません。

Mojoliciousの導入
Mojoliciousをインストールします。
$ sudo cpan Mojolicious

Mojoliciousをデーモンとして稼働させるためstarmanもインストールします。
$ sudo cpan Starman

WEBリモコン機能をスクリプトで作成
$ vi web_remocon

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Mojolicious::Lite;

# GETメソッドで「/」にアクセスしたときに行う処理を書く
get '/' => sub {
  my $self = shift;

  # 描画
  $self->render();
} => 'index';

get '/light_on' => sub {
  my $self = shift;

  system("sudo bto_ir_cmd -e -t 022000E70C976800000000000000000000000000000000000000000000000000000000");

  $self->flash(message => '【送信完了】シーリングライト 全光');
  $self->redirect_to('/');
} => 'light_on';

get '/light_night' => sub {
  my $self = shift;

  system("sudo bto_ir_cmd -e -t 022000E70C8F7000000000000000000000000000000000000000000000000000000000");

  $self->flash(message => '【送信完了】シーリングライト 常夜灯');
  $self->redirect_to('/');
} => 'light_night';

get '/light_off' => sub {
  my $self = shift;

  system("sudo bto_ir_cmd -e -t 022000E70C8B7400000000000000000000000000000000000000000000000000000000");

  $self->flash(message => '【送信完了】シーリングライト 消灯');
  $self->redirect_to('/');
} => 'light_off';

get '/aircon_on' => sub {
  my $self = shift;

  system("sudo bto_ir_cmd -e -t 0188004000148043422EDE230068000001000055000000000000000000000000000000");

  $self->flash(message => '【送信完了】エアコン 稼働');
  $self->redirect_to('/');
} => 'aircon_on';

get '/aircon_off' => sub {
  my $self = shift;

  system("sudo bto_ir_cmd -e -t 0188004000148043412EDE030068000001000052000000000000000000000000000000");

  $self->flash(message => '【送信完了】エアコン 停止');
  $self->redirect_to('/');
} => 'aircon_off';

# アプリ起動
app->start;

# 以下テンプレート(Mojo::Template)
__DATA__

@@ index.html.ep
<html>
  <head>
    <meta name="viewport" content="width=320, height=480, initial-scale=1.0, minimum-scale=1.0, maximum-scale=2.0, user-scalable=yes" />
    <title>室内リモコン</title>
  </head>
  <body>
    <h1>室内リモコン</h1>
    <%= flash 'message' %>

    <h2>シーリングライト</h2>
    <input type="button" value="全光" onClick="location.href='<%= url_for('light_on') %>'">
    <input type="button" value="常夜灯" onClick="location.href='<%= url_for('light_night') %>'">
    <input type="button" value="消灯" onClick="location.href='<%= url_for('light_off') %>'">

    <h2>エアコン</h2>
    <input type="button" value="稼働" onClick="location.href='<%= url_for('aircon_on') %>'">
    <input type="button" value="停止" onClick="location.href='<%= url_for('aircon_off') %>'">
  </body>
</html>

※ 各自、環境に合わせたスクリプトを書いてください。TEMPerを使って温度を表示しても良いかもしれません。

スクリプトに実行権限を与えてコマンドとして実行できるようにします。
$ chmod +x web_remocon
$ sudo mv web_remocon /usr/local/bin/

スクリプトが正常に実行され、WEBブラウザからアクセスできる事を確認します。
$ web_remocon

Raspberry Pi起動時に自動でスクリプトが実行されるように以下の行を追記します。
$ sudo vi /etc/rc.local

# WEB_REMOCON SERVER
su - pi -c 'starman --port=3000 --daemonize --pid=/tmp/web_remocon.pid /usr/local/bin/web_remocon'

これで、WEBリモコン機能の実装は完了です。

音声リモコン機能の実装

音声リモコン 制御プロトコルについての図
音声制御プロトコル図
※ 合言葉のもう一つ利点として、1つの部屋に複数の音声リモコン(ハードウエア)を設置しても合言葉を識別子として使用できるというのが上げられます。

Juliusで使用するサウンドデバイスの指定
USBマイクがサウンドデバイスとして認識されているか確認します。
$ sudo cat /proc/asound/modules

 0 snd_bcm2835
 1 snd_usb_audio

※ 各自、環境に合わせて読み替えて下さい。

USBマイクを接続するとJuliusが標準で使用されるデバイスファイル(/dev/dsp)とは異なるため環境変数で指定します。
$ sudo vi /etc/profile

export AUDIODEV=/dev/dsp1

Juliusの導入
必要なファイルをダウンロードしてきます。
$ wget -O julius-4.3.1.tar.gz \
> ‘http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz’
$ wget -O dictation-kit-v4.3.1-linux.tgz \
> ‘http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz’
※ コマンドが長いため折り返してあります。最新版が必要な場合はバージョンを調べてインストールしてください。

設定ファイルや辞書ファイルを設置するディレクトリを作成します。
$ sudo mkdir /etc/julius/
$ sudo mkdir /var/lib/julius/

Juliusをビルドしてインストールします。
$ tar zxvf julius-4.3.1.tar.gz
$ cd julius-4.3.1/
$ ./configure
$ make
$ make install

dictation-kitに含まれているファイルをコピーします。
$ tar zxvf dictation-kit-v4.3.1-linux.tgz
$ cd dictation-kit-v4.3.1-linux/
$ sudo cp model/lang_m/bccwj.60k.htkdic /var/lib/julius/
$ sudo cp model/phone_m/jnas-tri-3k16-gid.binhmm /var/lib/julius/
$ sudo cp model/phone_m/logicalTri /var/lib/julius/

単語辞書を作成します。
辞書ファイルを記述するとき、文字コードはUTF-8ではなくEUC-JPを使用します。文字コード切り替えは(:e ++enc=euc-jp)
$ vi /var/lib/julius/word.list

<sil>           []              silB
<sil>           []              silE
<sp>            []              sp
スタンバイ      [スタンバイ]    s u t a N b a i
ニュートラル    [ニュートラル]  n u t o r a r u
照明起動        [照明起動]      sh o u m e i k i d o u
ライト点ける    [照明起動]      r a i t o t u k e r u
照明停止        [照明停止]      sh o u m e i t e i sh i
ライト消す      [照明停止]      r a i t o k e s u
暖房起動        [暖房起動]      d a N b o u k i d o u
暖房点ける      [暖房起動]      d a N b o u t u k e r u
暖房停止        [暖房停止]      d a N b o u t e i sh i
暖房消す        [暖房停止]      d a N b o u k e s u
冷房起動        [冷房起動]      r e i b o u k i d o u
冷房点ける      [冷房起動]      r e i b o u t u k e r u
冷房停止        [冷房停止]      r e i b o u t e i sh i
冷房消す        [冷房停止]      r e i b o u k e s u

※ 各自、環境に合わせて単語辞書を書いてください。

Juliusの設定ファイル(テスト稼働用)を作成して記述します。
$ vi /etc/julius/julius_debug.conf

-w /var/lib/julius/word.list
-v /var/lib/julius/bccwj.60k.htkdic
-h /var/lib/julius/jnas-tri-3k16-gid.binhmm
-hlist /var/lib/julius/logicalTri
-n 5
-output 1
-input mic
-input oss
-rejectshort 600
-charconv euc-jp utf8
-lv 1500

※ 各自、自分に合わせて設定を書いてください。

Juliusの設定ファイル(本稼働用)を作成して記述します。
$ vi /etc/julius/julius.conf

-w /var/lib/julius/word.list
-v /var/lib/julius/bccwj.60k.htkdic
-h /var/lib/julius/jnas-tri-3k16-gid.binhmm
-hlist /var/lib/julius/logicalTri
-n 5
-output 1
-input mic
-input oss
-module
-rejectshort 600
-charconv euc-jp utf8
-lv 1500

※ 各自、自分に合わせて設定を書いてください。

Juliusをテスト稼働し音声コマンドを正常に認識できるか動作確認をします。
$ julius -C /etc/julius/julius_debug.conf

Raspberry Pi起動時に自動でjuliusが実行されるように以下の行を追記します。
$ sudo vi /etc/rc.local

su - pi -c 'nohup julius -C /etc/julius/julius.conf > /dev/null 2>&1 & echo $! > /tmp/julius.pid'

Open JTalkの導入
Open JTalkとその他必要なパッケージをインストールします。
$ sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic \
> htsengine libhtsengine-dev hts-voice-nitech-jp-atr503-m001
※ コマンドが長いため折り返してあります。

デフォルトは男性の音声ですが女性の音声を追加することもできるようです。
$ wget http://downloads.sourceforge.net/project/mmdagent/\
> MMDAgent_Example/MMDAgent_Example-1.4/MMDAgent_Example-1.4.zip
※ コマンドが長いため折り返してあります。
$ unzip MMDAgent_Example-1.4.zip
$ sudo cp -R MMDAgent_Example-1.4/Voice/* /usr/share/hts-voice/

Open JTalkを手軽に使用するスクリプトの記述
$ vi jsay

#!/bin/bash
WAV_FILE=/tmp/jsay_${RANDOM}.wav
#cd /usr/share/hts-voice/nitech-jp-atr503-m001
#cd /usr/share/hts-voice/mei_happy
cd /usr/share/hts-voice/mei_normal
echo "$1" | open_jtalk \
-td tree-dur.inf \
-tf tree-lf0.inf \
-tm tree-mgc.inf \
-md dur.pdf \
-mf lf0.pdf \
-mm mgc.pdf \
-dm mgc.win1 \
-dm mgc.win2 \
-dm mgc.win3 \
-df lf0.win1 \
-df lf0.win2 \
-df lf0.win3 \
-dl lpf.win1 \
-ef tree-gv-lf0.inf \
-em tree-gv-mgc.inf \
-cf gv-lf0.pdf \
-cm gv-mgc.pdf \
-k gv-switch.inf \
-s 16000 \
-a 0.05 \
-u 0.0 \
-jm 1.0 \
-jf 1.0 \
-jl 1.0 \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic \
-ow $WAV_FILE && \
aplay --quiet $WAV_FILE
rm -f $WAV_FILE

スクリプトに実行権限を与えてコマンドとして実行できるようにします。
$ chmod +x jsay
$ sudo mv jsay /usr/local/bin/

音声合成ができる事を確認します。
$ jsay 月が綺麗ですね

音声リモコン機能をスクリプトで作成
$ vi voice_remocon

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;

use 5.10.0;

use Encode;
use IO::Socket;

# 接続先情報にJuliusサーバを指定する
my $socket = IO::Socket::INET->new(
    PeerAddr => 'localhost',  # 接続先
    PeerPort => 10500,        # Port 番号
    Proto    => 'tcp',        # Protocol
    TimeOut  => 5             # タイムアウト時間
);

die("Could not create socket: $!") unless($socket);

# 待機モードのループ
while(1){
    my $msg = $socket->getline();
    my ($word, $cm) = &get_parameter($msg);

    # 誤認識による誤作動防止のための合言葉を判定
    # 認識の信憑性もCM値で確認する
    if($word eq "スタンバイ" && $cm >= 0.8){
        system("sudo jsay アクティブモードを開始します");

        eval{
            local $SIG{ALRM} = sub { die "timeout" };

            # タイムアウトする時間(秒)の設定
            my $timer = 30;

            # タイムアウト処理-開始-
            alarm($timer);

            # 音声コマンドの受付のループ
            while(1){
                my $msg = $socket->getline();
                my ($word, $cm) = &get_parameter($msg);

                # 認識の信憑性が一定である場合はコマンドを識別し実行する
                if($cm >= 0.8){
                    given($word){
                        when("ニュートラル"){
                            system("sudo jsay アクティブモードを終了します");
                            last;
                        }
                        when("照明起動"){
                            system("sudo jsay 照明を起動します");
                            system("sudo bto_ir_cmd -e -t 022000E70C976800000000000000000000000000000000000000000000000000000000");
                        }
                        when("照明停止"){
                            system("sudo jsay 照明を停止します");
                            system("sudo bto_ir_cmd -e -t 022000E70C8B7400000000000000000000000000000000000000000000000000000000");
                        }
                        when("暖房起動"){
                            system("sudo jsay 暖房を起動します");
                            system("sudo bto_ir_cmd -e -t 0188004000148043422EDE230068000001000055000000000000000000000000000000");
                        }
                        when("暖房停止"){
                            system("sudo jsay 暖房を停止します");
                            system("sudo bto_ir_cmd -e -t 0188004000148043412EDE030068000001000052000000000000000000000000000000");
                        }
                    }
                }
            }

            # タイムアウト処理-終了-
            alarm(0);
        };

        if($@){
            print $@ . "\n";
            system("sudo jsay ディアクテブモードになります");
        }
    }
}

# 渡されたXMLにUTF-8フラグを付けてWORDとCMを取得する関数
sub get_parameter(){
    my $msg = shift;

    my $text = decode_utf8($msg);

    if($text =~ /.+WORD="(\S+)".+CM="(\S+)"/){
        return ($1, $2);
    }else{
        return ("",  0);
    }
}

※ 各自、環境に合わせたスクリプトを書いてください。音声合成時には音声識別を停止しても良いかもしれません。

スクリプトに実行権限を与えてコマンドとして実行できるようにします。
$ chmod +x voice_remocon
$ sudo mv voice_remocon /usr/local/bin/

スクリプトが正常に実行され、音声コマンドにて制御できる事を確認します。
$ voice_remocon

Raspberry Pi起動時に自動でスクリプトが実行されるように以下の行を追記します。
$ sudo vi /etc/rc.local

su - pi -c 'sleep 30 && nohup voice_remocon > /dev/null 2>&1 & echo $! > /tmp/voice_remocon.pid'

これで、音声リモコン機能の実装は完了です。

将来性・拡張性について

今回は家電制御に重点を置いていますが、スクリプトをちょっと書き換えたり追加することにより、現在時刻や室内温度、天気予報、干満時刻、新着メール、ニュースヘッドライン、Twitterのタイムラインなどを音声コマンドだけで読み上げてくれるシステムを作成出来るでしょう。家電制御の面だけでも、ルンバの起動や、温度監視を行いエアコンを制御して室温を自動調整したり、リモコン式のOAタップと組み合わせることで赤外線リモコンに対応していない他の家電を制御することも可能になるかもしれませんので拡張性は大いにあるかと思います。

その他・補足について

マイクを取り付けている以上、Raspberry Piに侵入された場合、日常生活を盗聴される危険性があります。また、音声で家電を制御するということは当然ながらスピーカーを取り付けたパソコン越しからでも動作する事が実験でも分かっております。今のところ実害は無いと思いますが通話中など、パソコン越しや電話越しに家電を乗っ取られる可能性も十分に考えられますのでご注意ください。

参考サイト
株式会社 ビット・トレード・ワン | USB接続 赤外線リモコンキット
kjmkznr/bto_ir_cmd
Mojolicious::Liteでウェブツールを作ろう – Perl Advent Calendar Japan 2011 Casual Track
Devel/電子工作/RaspberryPi/日本語音声認識 – cubic9.com
Raspberry Pi で音声認識 – 猫ぱーんち!
Raspberry Pi でミクにしゃべらせよう | ぱわふる
橋本商会 » Raspberry Piに喋らせる
いつか、そのとき、あの場所で。 | [システム監視][Temper][Zabbix] Raspberry Piで、USB温度計を使って室温を計測する方法。

Raspberry Pi Wifi GW-USValue-EZ 安定させる ハードウエアを改造する前に要確認

Rapsberry Piに無線LANアダプタ(GW-USValue-EZ)を接続して使用していたところ、非常に不安定で作業中に度々切断されることから対策してみた。

これまでに、セルフ給電式のUSBハブの導入や、Raspberry Piのコンデンサ交換などを試みたが一向に解消する兆しがなかった。
それらのことから、無線LANアダプタについて調べたところ使用されているチップセットの省エネモードが原因であることがわかった。

ちなみに、PLANEX(GW-USValue-EZ)以外の無線LANでもチップセットがRealtekのRTL8192CUである場合は同様に対策できる。

結果が1であった場合、省エネモードで動いている
$ sudo cat /sys/module/8192cu/parameters/rtw_power_mgnt

設定ファイルを作成し下記の行を記述する
$ sudo vi /etc/modprobe.d/8192cu.conf

# Disable power management
options 8192cu rtw_power_mgnt=0

再起動して設定を適用する
# sudo reboot

参考サイト
Raspbian で Wi-Fi がスリープするのを防ぐ – CO’s Home ~ Boiling Water River & Morning Forever
linux – How do I disable suspend mode? – Raspberry Pi Stack Exchange

Twitter フォロワー同期(フォロー専用)Bot Perl 新API対応(改弐)

TwitterのAPIがすべてSSLになり403 forbiddenと表示されるようになったので対策してみました。

#!/usr/bin/perl
use utf8;
use strict;
use warnings;

# モジュール使用宣言
use Encode;
use FindBin;
use YAML::Tiny;
use Array::Diff;
use Net::Twitter;

# 現在のパスから見て設定ファイルを読み込み
my $config = (YAML::Tiny->read($FindBin::Bin . '/config.yml'))->[0];

# OAuth認証
my $twitter = Net::Twitter->new(
        traits           => ['API::RESTv1_1', 'OAuth'],
        consumer_key     => $config->{'consumer_key'},
        consumer_secret  => $config->{'consumer_secret'},
        apiurl           => 'https://api.twitter.com/1.1',
        searchapiurl     => 'https://api.twitter.com/1.1',
        legacy_lists_api => 0
);

$twitter->access_token($config->{'access_token'});
$twitter->access_token_secret($config->{'access_token_secret'});

# 認証失敗時の処理
die('Auth failed:'.$config->{'username'}) unless ( $twitter->authorized ) ;

# ユーザー名を含むユーザー情報を取得
my $own_id = $twitter->verify_credentials->{id};

my $nextc = -1; # paging default.
my @following_id_list; # outgo

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
        # パラメータcursorは前回取得したフォローイングまでの番号が入っている
        my $following_list = $twitter->friends_ids({ id=>$own_id, cursor => $nextc });
        $nextc = $following_list->{next_cursor};
        # 配列からフォローイングのidを取得
        foreach my $id (@{ $following_list->{ids} }){
                push(@following_id_list, $id); # 後で比較するためにフォローイングを配列に保管
        }
}while($nextc!=0);
# 文字昇順でソート
@following_id_list = sort @following_id_list;

$nextc = -1;
my @followers_id_list; # income

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
        # パラメータcursorは前回取得したフォロワーまでの番号が入っている
        my $followers_list = $twitter->followers_ids({ id=>$own_id, cursor => $nextc });
        $nextc = $followers_list->{next_cursor};
        # 配列からフォロワーのidを取得
        foreach my $id (@{ $followers_list->{ids} }){
                push(@followers_id_list, $id); # 後で比較するためにフォロワーを配列に保管
        }
}while($nextc!=0);
# 文字昇順でソート
@followers_id_list = sort @followers_id_list;

# 差分を取得(フォローイング)
my $diff_following = Array::Diff->diff(\@following_id_list, \@followers_id_list);

# 差分を取得(フォロワー)
my $diff_followers = Array::Diff->diff(\@followers_id_list, \@following_id_list);

# リムった人をリム返し
foreach my $delid_following (@{ $diff_following->{deleted} }){
        eval{$twitter->destroy_friend({user_id => $delid_following})};
        # プライベートだとエラーになる人がいるので確認用
        print $delid_following . "\n" if($@);
}

# フォローした人をフォロー返し
foreach my $delid_followers (@{ $diff_followers->{deleted} }){
        eval{$twitter->create_friend({user_id => $delid_followers})};
        # プライベートだとエラーになる人がいるので確認用
        print $delid_followers . "\n" if($@);
}

Perl SSH接続 Net::SSH2 使い方 CentOS5

PerlでSSHへ接続したくなったのでNet::SSH2を使ってみた
Net::SSH2を使うにはlibssh2-develを使用するらしいのでインストール
# yum -y install libssh2-devel

cpanを使ってNet::SSH2をインストール
# cpan -i Net::SSH2
# cpan -i Net::OpenSSH::Compat::SSH2

実装例
SSHでサーバにログインしてpublic_htmlに移動し、lsコマンドを実行する

#!/usr/bin/perl
use strict;
use warnings;
# SSHのバナーを表示したい場合
#use Net::OpenSSH::Compat::SSH2 qw(:supplant);
use Net::SSH2;

# バッファーサイズ
use constant BUFLEN => 512;

my $host = ""; # 接続先ホスト
my $user = ""; # ユーザ名
my $pass = ""; # パスワード

my ($len, $buf);

my $ssh2 = Net::SSH2->new();

$ssh2->connect($host) or die "$!";

if( $ssh2->auth_password($user,$pass)) {
    my $chan = $ssh2->channel();
    $chan->blocking(0);
    $chan->shell();

    $chan->write("cd public_html\n");
    select(undef,undef,undef,0.2);
    print $buf while ($len = $chan->read($buf, BUFLEN));

    $chan->write("ls -al ./\n");
    select(undef,undef,undef,0.2);
    print $buf while ($len = $chan->read($buf, BUFLEN));

    $chan->close();
}

これは色々使えそうですね

参考サイト
Perl Tips | Perl で、ssh でリモートのサーバにアクセスしてファイルをアップロード(SCP)する方法 (Net::SSH2)
自分イノベーション – 気まぐれ勉強メモ Net::SSH2を使ってみた
Net::SSH2と公開鍵
A little demo for Net::SSH2

Kali Linux システムモニタ(conky) インストール

Kali LinuxのデスクトップにCPU使用率やメモリ使用率などのシステム情報をクールに表示できるシステムモニタツール(conky)のインストールについてメモしておきます。

インストール
# apt-get install conky lm-sensors hddtemp

自動起動させる

# bash -c "echo '[Desktop Entry]'$'\n''Type=Application'$'\n''Exec=conky -p 5'$'\n''Hidden=false'$'\n''NoDisplay=false'$'\n''X-GNOME-Autostart-enabled=true'$'\n''Name=Conky' > ~/.config/autostart/conky.desktop"

設定
# vi ~/.conkyrc

use_xft yes
override_utf8_locale yes
xftfont MeiryoKe_Gothic:size=10
default_color d0d0d0
default_shade_color 003E3F
update_interval 2
own_window yes
own_window_type override
own_window_transparent yes
double_buffer yes
maximum_width 300
alignment top_right

TEXT
${font Bitstream Vera Sans:style=Bold:pixelsize=14}SYSTEM${font} ${hr 1}
Kernel: $alignr$kernel
Architecture: $alignr$machine
File system type: $alignr$fs_type

CPU ${alignr}${freq} MHz
${cpugraph 20,250 a0a0a0 ffffff -t}
RAM ${alignr}$mem / $memmax ($memperc%)
${membar 4}
Swap ${alignr}$swap / $swapmax ($swapperc%)
${swapbar}
Ether ${alignr}${addr eth0} 
Traffic $alignr up ${upspeed eth0} down ${downspeed eth0}
${upspeedgraph eth0 20,120 a0a0a0 ffffff -t} ${downspeedgraph eth0 20,120 a0a0a0 ffffff -t}
Wi-Fi ${alignr}${addr wlan0}
Traffic $alignr up ${upspeed wlan0} down ${downspeed wlan0}
${upspeedgraph wlan0 20,120 a0a0a0 ffffff -t} ${downspeedgraph wlan0 20,120 a0a0a0 ffffff -t}
DiskIO $alignr wrt ${diskio_write} read ${diskio_read}
${diskiograph_write 20,120 a0a0a0 ffffff -t} ${diskiograph_read 20,120 a0a0a0 ffffff -t}

Highest CPU $alignr CPU% MEM%
${top name 1}$alignr${top cpu 1} ${top mem 1}
${top name 2}$alignr${top cpu 2} ${top mem 2}
${top name 3}$alignr${top cpu 3} ${top mem 3}

Highest MEM $alignr CPU% MEM%
${top_mem name 1}$alignr${top_mem cpu 1} ${top_mem mem 1}
${top_mem name 2}$alignr${top_mem cpu 2} ${top_mem mem 2}
${top_mem name 3}$alignr${top_mem cpu 3} ${top_mem mem 3}

CPU temperature ${alignr}${hwmon 1 temp 1}℃
CPU fan speed ${alignr}${hwmon fan 1}rpm

※ 設定例なので各自自分に合った設定に換えてください。

実はこれ、デスクトップカスタム例としてよく写っていたりするのですが名称が分からなくて苦労しましたScreenshot_from_2013-10-07 17:00:53

Kali Linux Gnome Fallback (クラシック) モードからモダンモードに切り替える方法

調べ物をするため海外のフォーラムを見ていたらKali LinuxのFallbackモードからモダンモードに切り替える方法が載っていたのでメモしておく。
※ モダンモードにするとツールのジャンル分けなどがめちゃくちゃな状態になるのであまりお進めしない。。。

現在のモードの確認
# gsettings get org.gnome.desktop.session session-name

モダンモードへの切り替え
# dbus-launch gsettings set org.gnome.desktop.session session-name ‘gnome’

モダンモードはGnome拡張機能などを使いたい場合とかにはいいかもしれません

Screenshot_from_2013-10-07 10:35:39

参考サイト
Enable full gnome instead of gnome fallback

Twitter フォロワー同期(フォロー専用)Bot Perl 新API対応(改)

アカウントがプライベート設定のフォロワーがいると403 forbiddenになって処理が止まるようなので一応対策しました
手動で実行することで対象のID(数字)を確認出来ます

#!/usr/bin/perl
use utf8;
use strict;
use warnings;

# モジュール使用宣言
use Array::Diff;
use Net::Twitter::Lite::WithAPIv1_1;
use YAML::Tiny;
use Encode;
use FindBin;

# 現在のパスから見て設定ファイルを読み込み
my $config = (YAML::Tiny->read($FindBin::Bin . '/config.yml'))->[0];
# OAuth認証
my $twitter = Net::Twitter::Lite::WithAPIv1_1->new(
        traits => ['API::REST', 'OAuth'],
        consumer_key => $config->{'consumer_key'},
        consumer_secret => $config->{'consumer_secret'}
);
$twitter->access_token($config->{'access_token'});
$twitter->access_token_secret($config->{'access_token_secret'});

# 認証失敗時の処理
die('Auth failed:'.$config->{'username'}) unless ( $twitter->authorized ) ;

# ユーザー名を含むユーザー情報を取得
my $own_id = $twitter->verify_credentials->{id};

my $nextc = -1; # paging default.
my @following_id_list; # outgo

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
        # パラメータcursorは前回取得したフォローイングまでの番号が入っている
        my $following_list = $twitter->friends_ids({ id=>$own_id, cursor => $nextc });
        $nextc = $following_list->{next_cursor};
        # 配列からフォローイングのidを取得
        foreach my $id (@{ $following_list->{ids} }){
                push(@following_id_list, $id); # 後で比較するためにフォローイングを配列に保管
        }
}while($nextc!=0);
# 文字昇順でソート
@following_id_list = sort @following_id_list;

$nextc = -1;
my @followers_id_list; # income

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
        # パラメータcursorは前回取得したフォロワーまでの番号が入っている
        my $followers_list = $twitter->followers_ids({ id=>$own_id, cursor => $nextc });
        $nextc = $followers_list->{next_cursor};
        # 配列からフォロワーのidを取得
        foreach my $id (@{ $followers_list->{ids} }){
                push(@followers_id_list, $id); # 後で比較するためにフォロワーを配列に保管
        }
}while($nextc!=0);
# 文字昇順でソート
@followers_id_list = sort @followers_id_list;

# 差分を取得(フォローイング)
my $diff_following = Array::Diff->diff(\@following_id_list, \@followers_id_list);

# 差分を取得(フォロワー)
my $diff_followers = Array::Diff->diff(\@followers_id_list, \@following_id_list);

# リムった人をリム返し
foreach my $delid_following (@{ $diff_following->{deleted} }){
        eval{$twitter->destroy_friend({user_id => $delid_following})};
        # プライベートだとエラーになる人がいるので確認用
        print $delid_following . "\n" if($@);
}

# フォローした人をフォロー返し
foreach my $delid_followers (@{ $diff_followers->{deleted} }){
        eval{$twitter->create_friend({user_id => $delid_followers})};
        # プライベートだとエラーになる人がいるので確認用
        print $delid_followers . "\n" if($@);
}

シーザー暗号 ROT13 Perl 復号

ありきたりですがPerlで書いてみました

#!/usr/bin/perl
print sub{$_[0]=~tr/A-Za-z/ZA-Yza-y/
for(1..$_[1]);$_[0]}->($s=<>,$k=<>);

文字列 + 改行 + ずらす回数 + 改行 で実行できます

結構短く書けるものですね

Windows 7 シャットダウン時にプログラムがまだ閉じられていませんと表示させない

Windows 7を遠隔操作でシャットダウンした時に”プログラムがまだ閉じられていません”とシャットダウンしないことがあったため対策方法をメモしておきます。

Windowsキー+Rキーで”ファイル名を指定して実行”から”gpedit.msc”を起動します。
WS000052

“ローカルグループポリシーエディター”が起動したら、”コンピューターの構成”を選択します。
WS000053

“コンピューターの構成”が開いたら”管理用テンプレート”を選択します。
WS000054

“管理用テンプレート”が開いたら”システム”を選択します。
WS000055

“システム”が開いたら”シャットダウン オプション”を選択します。
WS000056

“シャットダウンをブロックするか取り消すアプリケーションの自動終了をオフにする”を起動します。
WS000057

“シャットダウンをブロックするか取り消すアプリケーションの自動終了をオフにする”が起動したら”有効”を選択し”適用”を押します。適用されたことを確認し、”OK”を押してパソコンを再起動します。
WS000058

再起動後は忌々しい”プログラムがまだ閉じられていません”が表示されなくなっていると思います。

参考サイト
Windows 7をプログラムの強制終了の問い合わせを出さずにシャットダウンする方法について

CentOS 5 バッファオーバーフロー攻撃 対策

RadHat系OSにはexec-shieldというカーネルレベルでのバッファオーバーフロー攻撃防御機能があるので有効にする方法をメモしておきます。

現在の設定の確認
# cat /proc/sys/kernel/exec-shield
1

1:基本無効
0:無効
2:基本有効(実行ファイルごとに有効にする)
3:基本的に有効(実行ファイルごとに無効にする)

手動による設定
# echo 2 > /proc/sys/kernel/exec-shield

設定ファイルによる設定(下記を追記する)
# vi /etc/sysctl.conf

# Exec Shield provides protection of buffer overflow attacks
kernel.exec-shield = 2

この設定でexec-shieldを有効化しても監視対象のプロセスを再起動しなければ意味は無いようなのでOSごと再起動しておく必要があるようである。