Category Archives: Linux (Server)

CentOS7 MongoDB3.2 インストール

調べると、まとまったサイトを見つけ出すことが出来なかったのでメモを残しておきます。

リポジトリ追加
$ sudo vi /etc/yum.repos.d/mongodb-org-3.2.repo

[mongodb-org-3.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.2.asc

インストール
$ sudo yum install -y mongodb-org

起動と自動起動の有効化
$ sudo systemctl start mongod
$ sudo systemctl enable mongod

管理者アカウントの作成
$ mongo

db.createUser(
  {
    user: "admin",
    pwd: "パスワードを指定してください",
    roles:
    [
      {
        role: "userAdminAnyDatabase",
        db: "admin"
      }
    ]
  }
)

mongoコマンドを実行すると警告が複数出るためそれの対策を行います
警告の内容についてはメモを残し忘れてしまいました・・・
$ sudo vi /etc/rc.local

# 以下追記
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
   echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

$ sudo chmod +x /etc/rc.d/rc.local

$ sudo vi /etc/security/limits.d/99-mongodb-nproc.conf

# ファイルを新規作成して以下を記述
*          soft    nproc     1024
root       soft    nproc     unlimited
mongod       soft    nproc     unlimited

*          soft    nofile    64000
*          hard    nofile    64000

認証の有効化 2.4系の設定が散乱しているようですが2.6系以降は以下の設定を行うようです。
$ sudo vi /etc/mongod.conf

security:
  authorization: "enabled"

未ログイン時
$ mongo

> db.system.users.find()
Error: error: {
        "ok" : 0,
        "errmsg" : "not authorized on test to execute command { find: \"system.users\", filter: {} }",
        "code" : 13
}

ログイン成功時
$ mongo admin -u admin -p

MongoDB shell version: 3.2.10
Enter password:
connecting to: admin
> db.system.users.find()
{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "****************", "storedKey" : "****************", "serverKey" : "****************" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }

SMTP-AUTH設定中にSASL認証をデバッグしてみた CentOS7

SMTP-AUTHに失敗する原因が分からず調べていると、SASL認証のテストを行うコマンド(testsaslauthd)が失敗する事に気づいたので、ちょっと色々とデバッグしてみました。
※ 原因は以下の内容とは無関係でした(一応、最後にちょこっと原因を書いてます)

※ 公開できない情報は以下の伏字にしております

+++ ユーザ名
*** パスワード
ドメイン

失敗時
# testsaslauthd -u +++ -p ***
# tail -f /var/log/audit/audit.log

type=USER_AUTH msg=audit(1469416320.791:907): pid=3559 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=? acct="+++" exe="/usr/sbin/saslauthd" hostname=? addr=? terminal=? res=failed'

成功時
# testsaslauthd -u +++ -p *** -s smtp
# tail -f /var/log/audit/audit.log

type=USER_AUTH msg=audit(1469416322.210:908): pid=3563 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=pam_unix acct="+++" exe="/usr/sbin/saslauthd" hostname=? addr=? terminal=? res=success'
type=USER_ACCT msg=audit(1469416322.210:909): pid=3563 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="+++" exe="/usr/sbin/saslauthd" hostname=? addr=? terminal=? res=success'

saslauthdをデバッグモードで起動してtestsaslauthdで失敗したコマンド、成功したコマンドをそれぞれ実行します
# saslauthd -d -a pam

saslauthd[3827] :do_auth         : auth failure: [user=+++] [service=imap] [realm=] [mech=pam] [reason=PAM auth error]

なぜか”/etc/pam.d/imap”を見ているらしいが、そんなものは無い・・・

とりあえず、smtpをimapにコピーします
# cp vi /etc/pam.d/smtp /etc/pam.d/imap
# saslauthd -d -a pam

saslauthd[3883] :do_auth         : auth success: [user=+++] [service=imap] [realm=] [mech=pam]

すると認証に通るようになりました
でも自分の環境ではtelnetして直接認証するとError: authentication failed: authentication failureが返ります

・・・以下、後日談・・・

SMTP-AUTHの認証をデバッグ

saslauthd[3611] :do_auth         : auth success: [user=+++] [service=smtp] [realm=...........] [mech=pam]

結論としてはSASL認証自体はしっかりimapではなくsmtpを使用しているので問題ではありませんでした

原因はテストに使用していたクライアントのhostsファイルに全然別のサーバのIPが定義されており
無関係なサーバにつないでいることが原因でした。。。

参考サイト
繰り返し的な処理を自動化する – いますぐ実践! Linuxシステム管理 / Vol.212

Fedora 23 SELinux が有効な状態で OpenVPN サーバに接続する

setenforceコマンドでPermissiveモードにして実際にOpenVPNに繋に行かせた時のログを元に
SELinux ポリシーの許可ルールを生成します

journalctl | grep openvpn | audit2allow -M openvpn_user_home

生成された.teファイルを開くと、どのようなルールが生成されたか確認できます

cat openvpn_user_home.te
module openvpn_user_home 1.0;

require {
	type openvpn_t;
	type user_home_t;
	class file open;
}

#============= openvpn_t ==============
allow openvpn_t user_home_t:file open;

生成されたルールに問題がなければ適用します

sudo semodule -i openvpn_user_home.pp

ESXi 6.0 u2 で vSphere Web Client と似た Web UIを無料で使う方法

先日、公開されたESXi6.0 update2にESXi Embedded Host Clientが含まれているようです。

ESXi Embedded Host Client – VMware Labsで公開されていた時は無償ライセンスだと
ISOのマウントどころかVMの電源管理すらライセンスエラーとのメッセージが出て使いない状態でした。

この機能が無償ライセンスでも利用できることがわかりましたのでアップグレード方法を載せておきます。
今回は、ESXi6.0 u1b から ESXi6.0 u2にアップデートしました。

VMWareのサイトからupdate-from-esxi6.0-6.0_update02.zipという名前のパッチをダウンロードします。
② ダウンロードしたパッチをESXi上のデータストアにアップロードします。
③ ESXi上にいるVMを全てシャットダウンします。
④ SSH、ESXiシェルを起動します。
⑤ メンテナンスモードにします。
⑥ SSHで接続して以下のコマンドを実行します。

# パッチまでのパスは必ず絶対パスである必要があります。
esxcli software profile update -d /vmfs/volumes/datastore1/update-from-esxi6.0-6.0_update02.zip -p ESXi-6.0.0-20160302001-standard

⑦ パッチの適用が終わったらメンテナンスモードを解除して再起動します。

https://ESXi6.0u2のホスト名/ui/ にアクセスすると以下のような画面が表示されます。
vSphere Client で使用するアカウントでログインします。
Screenshot from 2016-03-19 23-40-47

まだ、vSphere Clientで出来る事、全てができるわけではなさそうですが一通りの機能は利用できそうです。
Screenshot from 2016-03-20 00-08-21

ESXi6.0 + CentOS7.0 に vmware-tools をインストールする

気づいたらESXi6.0が出ていたので現在試しているのですが最小構成でインストールしたCentOS7.0にvmware-toolsをインストールしてみたのでメモしておきます。

必要なパッケージをインストールします
# yum -y install perl net-tools
※ net-tools は vmware-tools で ifconfig が必要なようなのでインストールします。

あとは基本的にCentOS6以前と同じ手順で、vmware-tools をインストールするだけです。
※ インストーラを起動すると open-vm-tools でなく vmare-tools を本当にインストールするか訪ねますが”yes”と答えればインストールできます。

WordPress + SQLite3 + Docker で1分もかけずにブログを作る

最近、Dockerイメージの作成がマイブームかも知れません。
今回はイメージさえあればWordPressを1分もかけずに構築できるイメージを作成してみました。

# vi Dockerfile

FROM centos:7

# 必要なパッケージをインストール
RUN yum -y update
RUN yum -y install httpd httpd-devel zip unzip tar wget
RUN yum -y install php php-xml php-pdo php-gd php-mbstring sqlite sqlite-devel

# WordPressをインストールしてSQLite3で動作するように設定
RUN wget https://ja.wordpress.org/latest-ja.tar.gz
RUN wget https://downloads.wordpress.org/plugin/sqlite-integration.1.8.1.zip
RUN tar xvfz ./latest-ja.tar.gz
RUN unzip ./sqlite-integration.1.8.1.zip
RUN rm -f ./latest-ja.tar.gz
RUN rm -f ./sqlite-integration.1.8.1.zip
RUN mv wordpress /var/lib/wordpress
RUN chown -R apache.apache /var/lib/wordpress
RUN mv /var/lib/wordpress/wp-config-sample.php /var/lib/wordpress/wp-config.php
RUN mv sqlite-integration /var/lib/wordpress/wp-content/plugins/
RUN mv /var/lib/wordpress/wp-content/plugins/sqlite-integration/db.php \
       /var/lib/wordpress/wp-content/

# ひな形を公開ディレクトリにコピーする
RUN cp -rpf /var/lib/wordpress/* /var/www/html/

# ログイン時にひな形から展開するように定義する
RUN echo "yes n | cp -ripf /var/lib/wordpress/* /var/www/html/ > /dev/null 2>&1" >> /root/.bash_profile

EXPOSE 80
VOLUME /var/www/html

RUN systemctl enable httpd

EXPOSE 80

# docker run --privileged -itd -p 8080:80 -v /root/wordpress/public_html:/var/www/html wordpress-sqlite bash -l -c "/sbin/init"

ブログの実態はホスト側で持つので保管先のディレクトリを作成
# mkdir -p /root/wordpress/public_html
# chmod 777 /root/wordpress/public_html

コンテナ起動
# docker run –privileged -itd -p 8080:80 -v /root/wordpress/public_html:/var/www/html wordpress-sqlite bash -l -c “/sbin/init”

ブラウザで http://127.0.0.1:8080 にアクセスしてWordPressのインストール画面が表示されれば成功です。

MySQLのコンテナを作成してDBとユーザを作ってボーリュームの指定をして・・・
というのが面倒だったので小規模ならSQLite3でもいいでしょ?っというノリで作ってみました。

Apacheを使いましたが、よくよく考えて見ればNginxでも良かったなと失敗した感が・・・。
そのうち、Nginxとphp-fpmとSQLite3を組み合わせたDockerイメージを作成してみたいと思います。

CentOS 7.0 Go言語 + revel な環境をDockerで構築する

revelとはGo言語で作られたWebアプリケーションフレームワークです。

Go言語自体はC++の代用を試みて開発されている言語なので高速で処理を行えます。
さらに、スクリプト言語に近い形で記述することができて並列処理も得意としています。

そんなGo言語を使って作られたフレームワークは当然のごとく爆速らしいです。

そんなGo言語+revelを最近流行りのDockerを使って開発環境を作りたいと考えました。

イメージとしては、こんな感じにしたいと思います。

1,「Go言語+revel」のイメージ
2,「MySQLなどのデータベース」のイメージ
2, ソースコードやデータベースファイルなどを管理する環境
※ 取りあえず、今回は(1)のみを作成します。

CentOS7.0にDockerのインストールを行う場合は特にリポジトリの追加も必要なく以下のような感じに行う事ができます。

# yum -y update
# yum -y install docker
# systemctl enable docker
# systemctl start docker

※ SELinuxやファイアウォールは各自で設定を行ってください。

雛形となるDockerイメージを作成します。
Dockerfileと呼ばれるファイルにコンテナの構成内容をガリガリ書いていきます。

# vi Dockerfile
FROM centos

RUN useradd revel

RUN yum -y update
RUN yum -y install golang git mercurial sqlite sqlite-devel

ENV GOPATH /var/gocode/
RUN echo 'export GOPATH="$GOPATH"' >> /etc/profile
RUN echo 'export PATH="$PATH:$GOPATH/bin"' >> /etc/profile

RUN mkdir /var/gocode/

RUN go get github.com/revel/revel
RUN go get github.com/revel/cmd/revel
RUN go get github.com/mattn/go-sqlite3

RUN source /etc/profile; revel help

USER revel

ENV HOME /home/revel/
ENV GOPATH /home/revel/gocode/

RUN mkdir -p /home/revel/gocode/{bin,pkg,src}

RUN echo 'export GOPATH="$GOPATH"' >> ~/.bash_profile
RUN echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.bash_profile
RUN echo 'yes no | cp -ripf /var/gocode /home/revel/ > /dev/null 2>&1' >> ~/.bash_profile

EXPOSE 9000
VOLUME /home/revel/gocode/src/

# docker run -it -p 9000:9000 revel bash --login
# docker run -it -p 9000:9000 --volume /root/src:/home/revel/gocode/src revel bash --login
# docker run -it -p 9000:9000 --volume /root/src:/home/revel/gocode/src revel bash --login -c 'revel run sample'

※ revelの実行は原則的にrevelユーザが行います。
※ revelの雛形は/var/gocode/の中に存在していてそれを元にログインのたびに初期化して使用します。
※ revelのソースコードはホスト側や別のコンテナなど外部のボリュームで管理できるようにします。

Dockerfileを元にイメージをビルドします。
イメージにはrevelというイメージ名を付けました。

# docker build --no-cache -t revel .

※ キャッシュを使用しないオプションをつけていますが必要なければ外してしまっても問題ありません。

イメージ一覧はこのように確認できます。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
revel               latest              fb1a981ee328        About an hour ago   753.7 MB
centos              7                   88f9454e60dd        2 weeks ago         223.9 MB
centos              centos7             88f9454e60dd        2 weeks ago         223.9 MB
centos              latest              88f9454e60dd        2 weeks ago         223.9 MB

ホストOS側にソースコードを格納するディレクトリを作成します。

# mkdir /root/src
# chmod 777 /root/src

イメージを元にコンテナを作成してシェルを起動し、フレームワークのサンプルを生成してみます。

# docker run -it -p 9000:9000 -v /root/src:/home/revel/gocode/src revel bash --login
$ revel new sample
$ revel run sample

ブラウザからアクセスできる事を確認します。
URLの例) http://127.0.0.1:9000

WS000010

このような画面が表示できたら一度終了して、ホスト側にソースコードが保存されている事を確認します。

# ls -al /root/src
合計 4
drwxrwxrwx  6 root root   74  3月 20 21:56 .
dr-xr-x---. 3 root root 4096  3月 20 22:19 ..
drwxr-xr-x  3 1000 1000   14  3月 20 21:56 code.google.com
drwxr-xr-x  5 1000 1000   45  3月 20 21:56 github.com
drwxr-xr-x  3 1000 1000   24  3月 20 21:56 gopkg.in
drwxrwxr-x  7 1000 1000  100  3月 20 21:56 sample # <-- これ

新たにコンテナを作成して今度は直接フレームワークを起動します。

# docker run -it -p 9000:9000 -v /root/src:/home/revel/gocode/src \
  revel bash --login -c 'revel run sample'

これで先ほどと同じようにブラウザでアクセスできるはずです。

取りあえず、イメージを作成してみて・・・
予想以上に試行錯誤したので中々大変でしたが、今後の開発に大きく影響を及ぼすような可能性を感じました。

参考サイト
» Docker上でRailsアプリケーション開発 TECHSCORE BLOG
Go – 「最速」フルスタックWebフレームワーク「revel」の紹介 – Qiita

CentOS7 ネットワーク設定 消えた ifconfig と system-config-network について

CentOS7がリリースされましたのでネットワークについて若干メモを残しておきます。

CentOS6以前は以下のコマンドでIPアドレスを確認していました

# ifconfig

CentOS7以降は以下のコマンドを使うようになるみたいです

# ip addr show

CentOS6以前は以下のコマンドを使用してネットワークやIPアドレスの設定をしていました

# system-config-network

CentOS7以降は以下のコマンドを使用してネットワークやIPアドレスの設定を行うようです

対話式の場合
# nmtui

コマンドラインベース
# nmcli

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