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

Ola Kae Tode Tai

すべてのエンジニアに、追い風を祈る

Railsアプリケーション作成(rails new)の覚え書き

Ruby Rails

Ruby on Railsアプリケーションを作成するときの備忘録です。

アプリケーションで使うRubyのバージョンをrbenvで固定

$ mkdir myproj
$ cd myproj/
$ rbenv local 2.2.4
$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-linux]

Gemfileを作成、編集

$ bundle init
$ echo 'gem "rails"' >> Gemfile

Railsをインストール

$ bundle install --path=./vendor/bundle --jobs=4

Railsアプリケーションを作成する

  • bundle installを行わない
  • javascriptを組み込まない
  • データベースの種類をMySQLにする
$ bundle exec rails new . --skip-bundle --skip-javascript --database=mysql

Gemfileを上書きしていいか聞かれるので Y で続行する。

あとはアプリケーションに応じてGemfileを編集して bundle install でインストール。

$ bundle install

Gitリポジトリを作成

/vendor/bundle.gitignore に追加して除外して、gitリポジトリを作成します。

$ echo "/vendor/bundle" >> .gitignore
$ git init
$ git add .
$ git commit

Ubuntu14.04にElasticsearch 2.1.1をインストールする

Elasticsearch Ubuntu

Ubuntu14.04にElasticsearch 2.1をインストールする方法の備忘録です。

f:id:kironono:20160125131108j:plain

ElasticsearchはLuceneベースの全文検索エンジンです。

Elasticsearch | Elastic

Elasticsearchの勉強をするためにインストールしてみます。Ubuntu14.04は適当なVagrant boxを探してきて用意しました。

構成

Elasticsearch 2.1.1はOracleかOpenJDKのJava 8 update 20またはJava 7 update 55より新しいバージョンのJVMが必要です。 今回はOpenJDKを使います。

  • Ubuntu 14.04
  • OpenJDK 1.8.0_72
  • Elasticsearch 2.1.1

OpenJDKをインストール

openjdk-8-jdkパッケージのインストール

OpenJDKのリポジトリを追加して、openjdk-8-jdkをインストールします。

vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get update
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get install software-properties-common
vagrant@vagrant-ubuntu-trusty:~$ sudo add-apt-repository ppa:openjdk-r/ppa
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get update
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get install openjdk-8-jdk

JAVA_HOME環境変数を設定

デフォルト環境変数JAVA_HOMEを設定して、再読み込みします。

vagrant@vagrant-ubuntu-trusty:~$ echo 'JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"' | sudo tee -a /etc/environment
JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
vagrant@vagrant-ubuntu-trusty:~$ source /etc/environment

バージョンの確認

インストールしたJavaのバージョンを確認します。

vagrant@vagrant-ubuntu-trusty:~$ java -version
openjdk version "1.8.0_72-internal"
OpenJDK Runtime Environment (build 1.8.0_72-internal-b05)
OpenJDK 64-Bit Server VM (build 25.72-b05, mixed mode)
vagrant@vagrant-ubuntu-trusty:~$ javac -version
javac 1.8.0_72-internal

Elasticsearchをインストール

リポジトリを追加

Elasticsearch 2.xのリポジトリを追加します。

vagrant@vagrant-ubuntu-trusty:~$ wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
OK
vagrant@vagrant-ubuntu-trusty:~$ echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list
deb http://packages.elastic.co/elasticsearch/2.x/debian stable main

Elasticsearchをインストール

パッケージリストを更新して、Elasticsearchをインストールします。

vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get update
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get install elasticsearch

自動起動の設定

システム起動時にelasticsearchサービスが起動するようにします。

vagrant@vagrant-ubuntu-trusty:~$ sudo update-rc.d elasticsearch defaults 95 10
 Adding system startup for /etc/init.d/elasticsearch ...
   /etc/rc0.d/K10elasticsearch -> ../init.d/elasticsearch
   /etc/rc1.d/K10elasticsearch -> ../init.d/elasticsearch
   /etc/rc6.d/K10elasticsearch -> ../init.d/elasticsearch
   /etc/rc2.d/S95elasticsearch -> ../init.d/elasticsearch
   /etc/rc3.d/S95elasticsearch -> ../init.d/elasticsearch
   /etc/rc4.d/S95elasticsearch -> ../init.d/elasticsearch
   /etc/rc5.d/S95elasticsearch -> ../init.d/elasticsearch
vagrant@vagrant-ubuntu-trusty:~$ sudo service elasticsearch start
 * Starting Elasticsearch Server                                                                                          [ OK ]

Elasticsearchの起動確認

デフォルトでは9200ポートでリッスンしています。 curllocalhost:9200 にアクセスするとノードの情報が返ってきます。

vagrant@vagrant-ubuntu-trusty:~$ curl -XGET localhost:9200
{
  "name" : "Ringo Kid",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.1.1",
    "build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
    "build_timestamp" : "2015-12-15T13:05:55Z",
    "build_snapshot" : false,
    "lucene_version" : "5.3.1"
  },
  "tagline" : "You Know, for Search"
}

プラグインをインストール

Elasticsearchでよく利用するプラグインをインストールしておきます。

analysis-kuromoji は日本語の分かち書きのためのプラグインです。

analysis-icuUnicode正規化をおこなうためのプラグインです。

lmenezes/elasticsearch-kopf はノードの管理をGUIで行なうことができるプラグインです。

github.com

analysis-kuromojianalysis-icu はElasticsearch 2.x になって公式がリリースするようになったようです。

vagrant@vagrant-ubuntu-trusty:~$ cd /usr/share/elasticsearch/
vagrant@vagrant-ubuntu-trusty:/usr/share/elasticsearch$ sudo bin/plugin install analysis-kuromoji
vagrant@vagrant-ubuntu-trusty:/usr/share/elasticsearch$ sudo bin/plugin install analysis-icu
vagrant@vagrant-ubuntu-trusty:/usr/share/elasticsearch$ sudo bin/plugin install lmenezes/elasticsearch-kopf

Elasticsearchの設定

開発環境用に設定を変更しておきます。

network.host はElasticsearch 2.xからデフォルトでlocalhostにバインドされるようになったようです。開発環境では外のIFからもアクセスしたいので指定しています。

vagrant@vagrant-ubuntu-trusty:~$ cat << EOF | sudo tee -a /etc/elasticsearch/elasticsearch.yml
> index.number_of_shards: 1
> index.number_of_replicas: 0
> network.host: 0.0.0.0
> EOF
index.number_of_shards: 1
index.number_of_replicas: 0
network.host: 0.0.0.0

再起動して設定を反映

再起動して、設定とプラグインを反映させます。

vagrant@vagrant-ubuntu-trusty:~$ sudo service elasticsearch restart
 * Stopping Elasticsearch Server                                                                                          [ OK ]
 * Starting Elasticsearch Server                                                                                          [ OK ]

KOPFの画面

http://localhost:9200/_plugin/kopf/ にブラウザでアクセスするとKOPFの画面が開きます。

ここからノードの状態を管理したり、簡単なクエリを発行したりできるみたいです。

(まだインデック等なにもない状態)

f:id:kironono:20160125125055j:plain

Elasticsearchに関する書籍

日本語の書籍は結構古いバージョンのElasticSearchのものしかないようです。

高速スケーラブル検索エンジン ElasticSearch Server

高速スケーラブル検索エンジン ElasticSearch Server

今のところ公式のドキュメントが一番よいみたいです。

Elasticsearch Reference [2.1]

Electric ImpでPWMを使ってLEDの明るさを制御する

ElectricImp Squirrel 電子工作

この投稿は Electric Imp Advent Calendar 2015 の11日目の記事です。

f:id:kironono:20151201001226p:plain

PWM制御

PWMとはPulse Width Modulationの略で、日本語ではパルス幅変調といいます。

パルス幅変調 - Wikipedia

一定の周期でON/OFFを繰り返すパルス信号のONとOFFの幅の比を調節することで元の電圧から1/5の電圧とか4/5電圧を作ることができます。

ElectricImpのGPIOどのポートでもPWMを使うことができます。

今回はElectricImpのPWM出力を使ってLEDの明るさを変化させてみます。

回路

f:id:kironono:20151203234528p:plain

利用する回路は以前のLチカの回路とおなじです。PIN9にLEDを接続しています。

デバイスのコードを書く

led <- hardware.pin9;
led.configure(PWM_OUT, 1.0 / 400, 0.0);

ledState <- 0.0;
ledChange <- 0.1;
 
function pulse() {
    led.write(ledState);
    
    ledState = ledState + ledChange;
    
    if (ledState >= 1.0 || ledState <= 0.0) {
        ledChange = ledChange * -1.0
    }
    
     imp.wakeup(0.05, pulse);
}

pulse();

WebIDEのデバイスパネルに上のコードを書きます。

led <- hardware.pin9;
led.configure(PWM_OUT, 1.0 / 400, 0.0);

PIN9の設定を行っています。PWM出力を使うので configurePWM_OUT と設定しています。2番目の引数は周期Tです。ここでは400Hzとしたいので 周期T = 1 / 周波数f を計算しています。3番目の引数はデューティー比Dの初期値です。最初はLEDをOFFの状態にしておきたいので 0 にしています。

led.write(ledState);

ここでPWM出力としたPIN9のデューティー比を設定しています。ここには 0.0 〜 1.0 までの値を設定します。仮に led.write(0.5) とするとデューティー比は0.5でLEDの明るさはだいたい半分になります。(LEDがONになっている時間が半分)

あとはLチカのときと同様に imp.wakeup を使って定期的に pulse 関数を実行するようにしています。

まとめ

PWM制御はモーターの制御や、今回のLEDのようにLCDモニターの輝度調整に使われていてとても身近なものです。いろいろ利用できそうですね! imp001はどのピンでもPWM出力が使えますが、ほかのImpの場合、どのピンがPWM出力に使えるかは以下から確認できます。

electricimp.com

Electric Impでタクトスイッチの入力をトリガに処理する

ElectricImp Squirrel 電子工作 Twilio

この投稿は Electric Imp Advent Calendar 2015 の10日目の記事です。

f:id:kironono:20151201001226p:plain

タクトスイッチを使った回路

ola.kironono.com

前回の「タクトスイッチの入力を読み取る」の回路と同じものを使います。

f:id:kironono:20151210214035p:plain

今回は回路はそのままに、タクトスイッチを押した時にLEDのON/OFFではなく、前々回に紹介したTwilioを利用してみましょう。

前々回の記事はこちらです。

ola.kironono.com

今回は、ElectricImpからTwilioを利用できるライブラリを使って、タクトスイッチが押されたら携帯電話にSMSを送るデバイスを作ってみます。

デバイスのコードを書く

#require "Button.class.nut:1.1.0"

led <- hardware.pin9;
led.configure(DIGITAL_OUT, 0);
button <- Button(hardware.pin7, DIGITAL_IN_PULLDOWN, Button.NORMALLY_LOW);

state <- 0;

button.onPress(function() {
    server.log("Button pressed");
    state = 1 - state;
    led.write(state);
    agent.send("sms.send", "こんにちは!こんにちは!!");
});

button.onRelease(function() {
    server.log("Button released");
});

前回のコードに以下の行を追加しました。

agent.send("sms.send", "こんにちは!こんにちは!!");

ElectricImpからTwilioのAPIを叩くライブラリはエージェントでしか利用できないので、デバイスのボタンがおされたことをエージェントに通知します。

第一引数にSMSで送信したいメッセージを渡しています。

エージェントのコードを書く

#require "Twilio.class.nut:1.0.0"

accountSID <- "xxxxx";
authToken <- "xxxxx";
twilioNumber <- "+1xxxxx";
recipientsNumber <- "+81xxxxx";
twilio <- Twilio(accountSID, authToken, twilioNumber);

function sendMessage(message){
    twilio.send(recipientsNumber, message, function(response) {
        server.log("twilio sent: " + response.statuscode + " - " + response.body);
    });
}

device.on("sms.send", sendMessage);
accountSID <- "xxxxx";
authToken <- "xxxxx";
twilioNumber <- "+1xxxxx";
recipientsNumber <- "+81xxxxx";

accountSIDauthToken はTwilioの管理画面からAPIクレデンシャルを確認して設定します。

twilioNumber はTwilioの管理画面から取得した電話番号です。 recipientsNumber はSMSの送信先の電話番号です。(Twilioをトライアルで利用している場合は、認証済みの電話番号のみ送信先に利用できます。)

function sendMessage(message){
    twilio.send(recipientsNumber, message, function(response) {
        server.log("twilio sent: " + response.statuscode + " - " + response.body);
    });
}

twilio.send でSMSを送信できます。第三引数のコールバック関数を指定しないとこの関数呼び出しはブロックされ、コールバック関数を指定すると非同期に処理されます。

実際に送ってみる

ビルドしてImpにデプロイします。

タクトスイッチを押すと、以下のようなSMSが送信されました!

f:id:kironono:20151215002447p:plain

Impのログは以下のように出力されました。

2015-12-15 00:04:57 UTC+9    [Status]    Agent restarted: reload.
2015-12-15 00:04:57 UTC+9   [Status]    Device connected
2015-12-15 00:05:06 UTC+9   [Device]    Button pressed
2015-12-15 00:05:06 UTC+9   [Device]    Button released
2015-12-15 00:05:07 UTC+9   [Agent] twilio sent: 201 - {"sid": "xxxxx", "date_created": "Mon, 14 Dec 2015 15:05:07 +0000", "date_updated": "Mon, 14 Dec 2015 15:05:07 +0000", "date_sent": null, "account_sid": "xxxxx", "to": "+81xxxxx", "from": "+1xxxxx", "body": "\u3053\u3093\u306b\u3061\u306f\uff01\u3053\u3093\u306b\u3061\u306f\uff01\uff01", "status": "queued", "dir[...truncated...]

簡単ですね!環境センサーの値を監視して条件を満たしたらSMSで通知みたいなことがお手軽に実現できます!

Electric Impでタクトスイッチの入力を読み取る

ElectricImp 電子工作 Squirrel

この投稿は Electric Imp Advent Calendar 2015 の9日目の記事です。

f:id:kironono:20151201001226p:plain

タクトスイッチを使う

f:id:kironono:20151210212022j:plain

前回まではデバイスのGPIOをデジタル出力に設定して、LEDを光らせていましたが、今回はGPIOのデジタル入力を試してみたいと思います。

タクトスイッチを使ってボタンを1回押したときにLEDをON。2回目を押したときにLEDをOFF。3回目はON...というように、スイッチを押すたびにLEDのONとOFFが切り替わるようにしてみます。

タクトスイッチの状態は、GPIOに3.3Vの電圧がかかった時に押されている、電圧がかかっていない時に離されているとします。

回路図

回路はこのようになります。

f:id:kironono:20151210214035p:plain

スイッチ周辺の回路がわかりにくいですが、図にするとこんな感じです。

f:id:kironono:20151210214758j:plain

スイッチが押されていないときは、PIN7とGNDが抵抗を介してつながっています。このときのGNDとPIN7の間の電圧は0Vになるので入力はLOWになります。

スイッチが押されたときは、3V3とPIN7がつながり、3V3とPIN7の間の電圧は3.3Vになり、入力はHIGHになります。

この時のスイッチとGNDの間に入っている抵抗はプルダウン抵抗と呼ばれるものです。一般的には、スイッチの場合はプルアップ抵抗を使う設計のほうがよいです。プルダウンの場合は、スイッチが押された時に無抵抗でPIN7とつながることに加え、PIN7を間違って出力に設定してしまうとショートすることになるためです。

プルアップの場合は、抵抗とスイッチの位置が逆になります。ですので、スイッチが押されていないときは、PIN7はHIGH、スイッチが押されている場合は、LOWとなります。

今回はスイッチが押されたときはHIGH、と実際の感覚と一致させるためプルダウンの設計にしました。

デバイスのコード

#require "Button.class.nut:1.1.0"

led <- hardware.pin9;
led.configure(DIGITAL_OUT, 0);
button <- Button(hardware.pin7, DIGITAL_IN_PULLDOWN, Button.NORMALLY_LOW);

state <- 0;

button.onPress(function() {
    server.log("Button pressed");
    state = 1 - state;
    led.write(state);
});

button.onRelease(function() {
    server.log("Button released");
});

Electric Impにはボタンの押下を扱うためのライブラリが用意されています。

#require "Button.class.nut:1.1.0"

上のコードでButtonクラスを使えるようになります。

electricimp.com

button <- Button(hardware.pin7, DIGITAL_IN_PULLDOWN, Button.NORMALLY_LOW);

Buttonクラスをインスタンス化します。PIN7をプルダウンで、押下していない時はLOWが入力されていることにしたので、そのように設定します。

button.onPress(function() {
    server.log("Button pressed");
    state = 1 - state;
    led.write(state);
});

button.onRelease(function() {
    server.log("Button released");
});

ボタンが押されたとき (onPress) 、離されたとき (onRelease) のコールバックを設定しています。

ボタンが押されたときにLEDの状態 state を変更し、PIN9を状態に応じた出力に設定します。

ボタンが離されたときは、ログの出力だけします。

まとめ

デプロイして動かしてみます。ボタンを押すたびにLEDの点灯と消灯が切り替わればOKです。 本来であれば一定時間ごとにPIN7の入力状態がHIGHからLOW、LOWからHIGHになる部分を監視するコードを書かなければいけませんが、Buttonライブラリを使うとその部分をやってくれるので多少楽ができ、コードの見た目もすっきりします。