Slack OAuth を 簡単にするツールを作った

前回 Slack の ボット に OAuth で 権限を付与する方法 について書いたものの、ブラウザで頑張るのは結構めんどくさいよなぁと. なのでツールを作ってみました. まだ細かいところまで作り切れてないですが、少し使う分にはいけそうなので、ちょっと脱線してトークン活用の前にツールをご紹介.

作業環境

  • Slack
  • Windows 10
  • Google Chrome

Slack OAuth Helper

命名苦手なので、まんまの名前です.
GitHub リポジトリ https://github.com/azriton/slack-oauth-helper に ソース一式をアップし、GitHub Pages を master ブランチで設定したので、https://azriton.github.io/slack-oauth-helper/ で 動作しています. GitHub すごい!

設置を簡単にしたかったので HTML 1枚 で できています. 外部依存は Modulr.css という CSS ライブラリ と Font Awesome で、JavaScript は ライブラリなしです.
HTML5 で 追加された <template> タグ や SessionStorage, Selectors API などを使っていますが、最近のブラウザだったら大丈夫だと思います. たぶん. 環境の都合で、Windows 10 の Google Chrome と Microsoft Edge でしか動作確認してないです. すみません.
なんか、document.querySelectorAll()for-of で Chrome と Edge で 動きが違ったりしたので若干不安ではありますが…

使い方

アプリ・ボット の Redirect URL を 修正

ここではアプリ・ボットは登録されているものとして、Redirect URL の 変更から始めたいと思います.

Slack の Apps https://api.slack.com/apps へ アクセスし、利用するボットを選択します.

ボットの詳細画面が表示されるので、左メニューから [OAuth & Permissions] を クリックします.

画面中ほどの [Redirect URLs] にある、URL の 右にある [ペンのアイコン] を クリックします.

URL が 編集できるようになるので、https://azriton.github.io/slack-oauth-helper/ を 入力し、[Save] ボタンをクリックします. 最後の / を 忘れないようにご注意ください.

編集が完了します. 下にある [Save URLs] ボタンをクリックします. (こっちの Save も しないと確定されないのでご注意. よく忘れてトラブりました…)

Slack OAuth Helper の 利用

https://azriton.github.io/slack-oauth-helper/ へ アクセスします.
[Client ID] に アプリ・ボット の Client ID を 入力します.
[OAuth Scopes] で 必要な権限にチェックを入れていきます. ここでは 前回と同じスコープ に チェックしました.
権限選択後、[認可リクエスト] ボタンをクリックします.

Slack の Slack の OAuth 権限確認画面 が 表示されます. 権限の詳細を確認し、問題なければ [Authorize] ボタンをクリックします/

Slack OAuth Helper に 戻ります. トークン発行済みの場合は権限が更新されているので完了となります.
未発行の場合は、[トークン発行 URL] に 表示されている URL を コピーします. テキストフィールド右 の ファイル・アイコン を クリックすると、クリップボードへコピーされます. ブラウザのアドレスバーへペーストし REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET を アプリ・ボット の Client Secret に 置き換えてからアクセスします.

※ トークン発行については、あえてフォームを作りませんでした. HTML 単独で動作しているので Client Secret を 抜くことはないのですが、この類のデータは不要なら入力欄は作りたくないという考えからになります. ここだけは手間が残りますが、大事なものは知らない場所に入力しない ってことでご容赦ください.

Known Bugs とか、ToDo とか

  • フォーム で required に なっているのに、効いてません. 未入力でも Slack OAuth へ 遷移して、エラーになります. orz
  • Slack OAuth Helper を 開く URL に パラメーター を つけると、設定を復元して画面表示できる機能があるけど、URL を 作る機能が未実装です. orz
  • トークン発行済み って スイッチ を 用意して、Slack OAuth 後の戻り画面を切り替えたい.
    いずれ GitHub Issues に 入れておかないと…


これで Slack の OAuth 権限の設定が少し簡単になりました. 最小権限で作り始めて、必要になってから追加するので、なんだかんだで権限が欲しくなり、そのたびに URL を 作るのもしんどかったので、思い切って作ってよかった.

自分が権限を持っている Slack チーム だと 自己完結できるので良いのですが、一般ユーザの権限しかないところでボットを作っていたりすると、OAuth を お願いしなければならないケースもあり、その際に管理者さまがすぐにやってくれるとよいのですが、いろいろとあると進まないので、こんな画面で渡すと意外と早かったりして助かります. 管理者さまへ簡単に渡せるように設定復元 URL を 作る機能を早く実装しないと.

Slack の ボット に OAuth で 権限を追加する

Slack の ボット を 自然言語で会話させたり、リマインド系の処理をさせたりと色々できるようになりました. もう少し踏み込んで Slack の API を 活用した処理をできるようにしたいと思います. そうなると、これまでの Bot トークンでは権限が足りず、処理ができません. まずは準備として Slack の ボット に OAuth で 権限を追加したいと思います.

作業環境

  • Windows 10
  • Slack
  • A3RT Talk API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.4

アプリ・ボット の 作成

OAuth で ボットに権限を追加するには、アプリ・ボット(勝手に命名! App じゃ わかりにくいので.) を 作って、そちらで動作させる必要があります. これまでのボットは残念ながらサヨナラに (T_T とはいえ、Slack でのアカウントだけなので、作ってきたプログラムは そのままに動作させられます.

アプリ・ボット作成のページ https://api.slack.com/apps/new へ アクセスします.
[App Name] に アプリ・ボット の 名前を入力し、[Development Slack Team] で 自分の Slack チーム を 選択します.
[I plan to submit~] は、作成したボットを Slack App Directory で 公開する場合にチェックをつけますが、今回はなしで [Create App] ボタンをクリックして進めました.

アプリ・ボットが作成され基本情報の画面が表示されます. [Client ID] と [Client Secret] は 後で使うのでひかえておきます. Client Secret は [Show] ボタンをクリックすると表示されます. 特に大事なので取り扱いに注意します.

左メニューから [OAuth & Permission] を クリックし、画面中央の [Redirect URL(s)] に http://localhost:3000/slack/auth/redirect を 入力し、[Save Changes] を クリックします.
これは Slack の OAuth から リダイレクト・バックされる際の URL に なります. 通常はアプリを動かしておくのですが、今回は手動でブラウザ内完結するので localhost に しました. 詳細は こちら、Sign in with Slack も ご参照ください.

続いて Slack に ボットのユーザを追加します. 左メニューから [Bot Users] を クリックします.
[Default username] に Slack の ボット・ユーザー名を入力します. 既存のユーザー名と重複すると、自動的に連番が付与されるので注意してください.
入力後 [Add Bot User] を クリックします.

OAuth で 権限を追加

Slack の OAuth Scopes の ページから、必要な権限をピックアップします. 今回は、今後使っていきたい想定で bot, channels:history ,emoji:read, files:read, files:write:user, users:read の権限を取得することにしました.
※ 本来は必要になり次第、以下の手順で追加していくべきですが、一連の流れで作っていくのでまとめて取得しました. あまりとりすぎるとボットができる範囲が大きくなりすぎるので、何かあった際の影響も大きくなるため権限の設定は注意が必要です.

2017年6月7日 追記
以下の手順を簡易化するためのツールを作りました. よろしかったら、こちらもご利用ください.
Slack OAuth Helper - https://azriton.github.io/slack-oauth-helper/

必要な権限のスコープが決まったのでブラウザで https://slack.com/oauth/authorize?client_id=REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID&scope=REPLACE_THIS_WITH_YOUR_OAUTH_SCOPE へ アクセスします.
REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID は、先ほどアプリ・ボットを作成した際にひかえた [Client ID] を、
REPLACE_THIS_WITH_YOUR_OAUTH_SCOPE は、上記で選択した OAuth Scope を カンマつなぎ (e.g. bot,channels:history,emoji:read,files:read,files:write:user,users:read)で置き換えます.

そうすると、Slack の OAuth 権限確認画面が表示されます. 与える権限の内容を確認し問題なければ [Authorize] ボタンをクリックして認可します. (複数の Slack チーム に サインインしている場合はチーム選択が先に表示されるので、アプリ・ボットを使うチームを選択します.)

ブラウザが localhost へ リダイレクトされ、ページが表示できないエラーが表示されます. 慌てずに、アドレスバー の URL から code の 値をコピーします.
※ このリダイレクトされた先は、先にアプリ・ボットを作成した際に [OAuth & Permission] の [Redirect URL(s)] に 入力したものになります. 本来は OAuth で 連携したアプリに戻してプログラムで処理するのですが、今回は手動でやりきります.

ブラウザで、https://slack.com/api/oauth.access?client_id=REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID&client_secret=REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET&code=REPLACE_THIS_WITH_COPYED_CODE へ アクセスします.
置き換えは以下となります.

  • REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID は、先にアプリ・ボットを作成した際にひかえた [Client ID]
  • REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET は、先にアプリ・ボットを作成した際にひかえた [Client Secret]
  • REPLACE_THIS_WITH_COPYED_CODE は、上記ブラウザのリダイレクトで戻されたアドレスバーの URL code の 値

正しく入力できるとトークンが含まれた JSON が 返ります. access_tokenbot_access_token を、それぞれひかえておきます.
access_token は Slack の API を 呼び出す際に使うトークンで、bot_access_token は ボットを起動する際に使用するトークン(これまで使ってきたトークンと同じ位置づけ) です.

とりあえず、ボット を 起動

今回は OAuth の 権限を持ったボットの作成で準備段階なので、基本動作 の Botkit readme.md #Basic Usage の まま index.js を 作ります.

1
2
3
4
5
6
7
8
9
10
const Botkit = require('botkit');
const controller = Botkit.slackbot();

controller.spawn({
token : process.env.bot_access_token
}).startRTM();

controller.hears('hello', [ 'direct_message', 'direct_mention', 'mention' ], (bot, message) => {
bot.reply(message, 'Hello yourself.');
});

ボットのプログラムができたら起動します.
[API_TOKEN] は Slack からコピーした、ボットの API Token に なります.

1
2
3
4
5
6
7
8
9
10
c:\Develop\repos\slack-bot> set access_token=[ACCESS_TOKEN]
c:\Develop\repos\slack-bot> set bot_access_token=[BOT_ACCESS_TOKEN]
c:\Develop\repos\slack-bot> npm install --save botkit
c:\Develop\repos\slack-bot> node index.js
Initializing Botkit v0.5.4
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.connect
notice: ** BOT ID: dev-anonymous-poet ...attempting to connect to RTM!
notice: RTM websocket opened



OAuth の 権限を使ったボットの作成は、ちょっと長くなりそうなので今回は権限の取得まで…
もうちょっと やりたかったけど仕方ない. ボットが色々な権限を持つことで Slack 内でのちょっとしたお手伝いができるようになるので便利になりそうですね.

Slack ボット の AIトーク機能 を Docomo の API に 切り替える

Slack の ボット を リクルートテクノロジーズさん の API を 使って自然言語での会話できるようにしてみました. AI が 流行っている 2017年昨今、様々なサービスがあるのでいろいろ試してみたいと思います. 今回は NTTドコモさん の AIトーク の API を 試してみました.

作業環境

  • Slack
  • docomo Developer support 雑談対話 API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.2

docomo Developer support とは ?

NTTドコモさん が 公開されている AI の API で、 “ドコモやパートナー企業が持つ様々なアセットを「API」として汎用化して提供 – docomo Developer support” してくれるものだそうです. 会話を意識した API では 音声認識や音声合成による読み上げなどの API があり、また 画像認識 や 面白いところでは、山座同定 - 画像に写っている山の名前を取得、仮想フェンス、交通情報 などなど、様々な API が 用意されています. NTTドコモさん の スマートフォン・アプリで使われている機能+αで提供されているような感じでしょうか.

今回は その中の 雑談対話 API “自然な会話をします。 – API/ツール“ を 使わせていただきました. ウェブサイト で おすすめ されている Repl-AI の 方が高機能なイメージがありましたが、シナリオベースで動かすような感じで、チャット上での雑多な会話に応答するには 雑談対話 API が よさそうでした.

docomo Developer support に ユーザ登録

API の 利用にあたり、まずは docomo Developer support に ユーザ登録する必要があります.

ログイン の ページへアクセスし、SNSアカウントでログイン / 新規登録 を します. 今回は [メールアドレスで新規登録] 選択しました.

メールアドレスの入力ページが表示されるので、[メールアドレス] と [確認用] に それぞれ 入力します.
[所属されている法人・組織に関する情報を登録する] は、今回は個人利用なのでチェックを外しました. 登録すると利用制限が緩和されるようです. 最初からチェックが入っており、会社名などが必須で表示されているので焦りますが、チェックを外すことで会社名などの項目は消えます.
最後に [文字認証] の 画像に表示されている文字列を入力し、利用規約を確認し、同意できたら [同意して確認画面へ] ボタンをクリックします.

確認画面が表示されるので、メールアドレスに間違えがないか確認し [仮登録する] ボタンをクリックします.

メール送付のステップに進み、確認メールが送信されたとの画面が表示されます.
ここで、先ほど入力したアドレスにメールが届くのを待ちます.

メールに書かれている URL へ アクセスすると、パスワード入力の画面が表示されます. 注意事項に従ったパスワードを決め入力し [パスワードを設定する] ボタンをクリックします.

パスワードが設定できると、新規アカウント登録完了の画面が表示します. 続いて API key を 取得するので、[ログインする] ボタンをクリックします.

雑談対話 API の 利用申請 と API key の 取得

アカウント作成の流れから ログイン画面 は 表示されますが、自動ログインや入力はないので、先ほど取得した アカウントのメールアドレスとパスワードでログインします.

マイページ画面が表示されるので、画面中ほどの API利用申請・管理 から [新規API利用申請へ] ボタンをクリックします.

アプリケーションの登録画面が表示されるので、情報を入力します.
審査の話が書かれていますが、今回はすぐに API key が 発行されました.
開発用の仮登録なので審査はなく、本登録時に審査があるのでしょうかね. 審査の説明があってちょっとドキドキしましたが…

コールバック URL は、今回は OAuth を 使わないので注釈の通り https://dummy と 入力しました. OAuth を 使うと、個人に応じた会話をしてくれるようです.
提供者名とサポートメールアドレスは OAuth 画面で使われるようで、今回は OAuth は 使わないのですが必須なので入力します.
入力後 [API 機能選択へ] ボタンをクリックします.

API 機能選択画面が表示されます. 今回は [雑談対話] のみを選択し [利用する API の 利用規約に同意して、次へ] ボタンをクリックします. 同意すべき利用規約が画面内にないのですが、アカウント作成時に同意した ご利用規約 で よいのかと思います.

利用規約に同意できたら、利用申請画面が表示されます. 選択した機能が表示されていることを確認し [利用申請する] ボタンをクリックします.

利用申請が完了しました! 続いて API key を 確認するため [登録アプリケーション一覧へ] ボタンをクリックします.

API利用申請・管理 画面が表示されます. アプリケーション情報 に 先ほど登録したアプリケーション名があり、client id、client secret、API key が 表示されています. 今回は API key のみ使用するので控えておきます.

Slack の ボット を 改修

前回のトーク機能を以下のように変更します.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const Botkit = require('botkit');
const request = require('request');

const controller = Botkit.slackbot();

controller.spawn({
token: process.env.token
}).startRTM();

var contexts = {};
controller.on('ambient', (bot, message) => {
request.post({
url: `https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=${process.env.docomo_apikey}`,
json: {
utt: message.text,
context: contexts[message.user],
t: 20
}
}, (err, response, body) => {
if (body && body.utt) {
contexts[message.user] = body.context;
bot.reply(message, body.utt);
} else {
bot.reply(message, `エラーたよ:fearful: [${body}]`);
}
});
});

ambient の イベントを受けるのは変わらず、request 先が変わります.
url の API URL が 変わり、URL に 続いて ?APIKEY=${process.env.docomo_apikey} で API key を 渡します. リクエスト・パラメータに入れたかったのですが、どうしてもうまく動かなかった orz
リクエスト・パラメータ は json で 以下のデータを送ります.

  • utt は、API へ 渡す会話の文字列です. この入力に対して応答を考えて返してくれます. Slack の 入力なので message.text を 渡します.
  • context は、会話の継続を識別する ID とのことで API からのレスポンスに含まれる context を 再度渡すことで会話の継続ができるようです. Slack では 複数のユーザーが会話してくるので、ユーザーごとに context を とっておき渡すようにしました. (こうすると会話の横入りができないので、全員で共通でもよかったかも)
  • t は、キャラクター指定になります. 20 で 関西弁キャラ、30 で 赤ちゃんキャラ、指定なし で デフォルトキャラ だそうです. 会話の雰囲気を変えてみたかったので関西弁にしてみました.
    他にも会話しているユーザー の ニックネーム や 血液型、星座 などなど 多数のパラメーターが設定できます. 詳細は 機能別リファレンス を ご確認ください.

レスポンスの本体は body に 入ってきます. body.utt が レスポンスの会話なので、bot.reply() に 流します. また body.context に 会話のコンテキストが入っているので、request で 使用した var contexts に Slack の ユーザである message.user を キーに保持しておきます.
この形だとボットを再起動するなどして変数がクリアされると消えてしまいますが、永続化するほどの情報ではないので変数保持としました.

いざ、起動!

前回同様 Slack トークン と API Key を 環境変数から受け取るので環境変数を設定して起動します.

1
2
3
4
5
6
7
token=REPLACE_THIS_WITH_YOUR_TOKEN docomo_apikey=REPLACE_THIS_WITH_YOUR_APIKEY node index.js
Initializing Botkit v0.5.2
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.start
notice: ** BOT ID: bot ...attempting to connect to RTM!
notice: RTM websocket opened

※ Windows コマンドプロンプト の 場合は、下記のように set で 明示的に環境変数を設定してから実行します.

1
2
3
set token=REPLACE_THIS_WITH_YOUR_TOKEN
set docomo_apikey=REPLACE_THIS_WITH_YOUR_APIKEY
node index.js

トーク、トーク♪


前回の流れ同様の会話で始めましたが、いきなりよくわからない応答です. そして好きなんですかね、オフィス街…
会話が詰まってくると疑問を投げかけてきて話題を変えるような応答もしてきます. これはこれで面白い感じです.



ボットのフレームワーク に AI の サービス と、組み合わせるだけで簡単に会話ボットが作ることでき、また AI も Web API なので、切り替えも簡単にできました. フレームワークうやサービスを提供してくれてるおかげですね. ありがたいです.

個人的には、リクルートテクノロジーズさん の API に 比べて、NTTドコモさん の API のが、より自然な会話応答をしているようにも感じました. 途中で話を変えてきたり、ニュースをブチ込んできたりと色々と楽しいです. 例のヒツジさん あたりで培われている技術なんですかね.

サービスごとの特色があって面白いです. 次はどこの AI と 会話してみようかなぁ.

Slack の ボット に AIトーク機能を付ける

Slack の ボット で 自然言語での会話できるようにしてみたいという野望があるものの、個人ではなかなか太刀打ちできません. こんなときは巨人の肩、ですね. というこで、最近公開された リクルートテクノロジーズさん の AI を 使って、Slack の ボットにトーク機能を付けてみたいと思います. はたしてちゃんと会話が成立するボットになるのか、楽しみですね♪

作業環境

  • Slack
  • A3RT Talk API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.2

A3RT API とは ?

リクルートテクノロジーズさん が 公開されている AI の API で、機械学習 や ディープラーニング(深層学習) を 用いた API だそう. ホットペッパービューティー や カーセンサー などで活用されれいたのだとか. 2017年4月現在、6種類 の API が 提供されていて、今回は その中の Talk API “様々なアプリケーション上でユーザーとの対話を自動化するAPIです。入力文から応答文を自動生成します。日常会話レベルでの応答が可能です。 – プレスリリース“ を 使わせていただきました.

A3RT Talk API の API KEY 発行申請

さっそく、A3RT Talk API を 利用するために、API KEY を 発行してもらいます.

Talk API の ページへアクセスし、[API KEY 発行] を クリックします.

メール確認の入力ページが表示されるので、まずは [利用規約、プライバシーポリシーに同意する] を クリックします.

画面内にウィンドウが表示され、利用規約 と プライバシーポリシー が 表示されます. 確認して、同期できたら [同意する] ボタン を クリックします. 同意できない場合は利用できないので、その場合は利用をあきらめましょう…

利用規約 と プライバシーポリシー に 同意すると、ウィンドウが閉じるので、利用者申請をするメールアドレスを入力し、[送信] ボタンをクリックします.

ステップ2へ進み、確認メールが送信されたとの画面が表示されます.
ここで、先ほど入力したアドレスにメールが届くのを待ちます.

メールに書かれている URL へ アクセスすると、メールアドレスの確認完了の画面が表示されます. 続いて同じメールアドレスに API KEY が 送られてきます.
API KEY を 受け取ったら、申請完了になります.

Slack の ボット に 設置

基本動作の確認確認として、Botkit の readme.md #Basic Usage を 使います. そして fail というキーワードでメンションをかけられたら、処理が失敗するコードを追加します.
余談ですが、最近 GitHub の Botkit Readme.md が 変わって、基本動作のソースが docs/readme.md へ 移動し、またソースが少しわかりにくくなってしまいました. 困るなぁ…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Botkit = require('botkit');
const request = require('request');

const controller = Botkit.slackbot();

controller.spawn({
token: process.env.token
}).startRTM();

controller.on('ambient', (bot, message) => {
request({
url: 'https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk',
method: 'POST',
form: { apikey: process.env.a3rt_talk_apikey, query: message.text },
json: true
}, (err, response, body) => {
if (body.status == 0) {
bot.reply(message, `${body.results[0].reply} (${Math.ceil(body.results[0].perplexity * 100) / 100})`);
} else {
bot.reply(message, `エラーたよ:fearful: [${body.status} ${body.message}]`);
}
});
});

今回はチャンネル内で自由に会話応答したいので ambient の イベントを受けるようにしました. メンションでの応答にすると毎度つけるのがめんどくさいというのもあり. とはいえ、メンション以外のすべてに応答するので、ほぼ常時反応します. 本番で使う場合は専用ボットにしてチャンネルを限定したほうが良いかもしれません.

会話を受け取ったら Talk API を 呼び出して応答します. Talk API は HTTP POST で https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk へ リクエストします. リクエスト・パラメータ は apikeyquery です.
apikey は、発行申請した際にメールで受け取ったものになります.
query は、Talk API へ 渡す会話の文字列です. この入力に対して応答を考えて返してくれます. Slack の 入力なので message.text を 渡します.

今回は request モジュールを使って実装しました. json: true を 設定すると、レスポンスを自動的に JSON オブジェクト として返してくれるので実装が簡単になります.
レスポンスの本体は body に 入ってきます. HTTP Status も しっかり切られているのですが、empty reply 応答テキストが空 の 場合 も 200 OK で 返ってきて無反応な場合が分かりにくかったので、API の Status コードで応答を振り分けました.

body.status == 0 は 正常に応答しているので、そのまま Slack へ リプライします. 応答メッセージは body.results[0].reply に 入っています. 2017年4月現在 results は 1つしか返ってきませんが、いずれ複数返ってくるようになるのでしょうか. また、body.results[0].perplexity に 予測性能 が 入っています. 数値が高いほど確度がよさそうに感じますが、詳細はドキュメントにありませんでした. 今回はテスト用に出力しています. 数値に合わせて絵文字をあてても面白いかもしれません.

body.status0 以外の場合は、何かしらのエラーになります. 今回はデバッグ用に Slack へ リプライさせています. 実際にはログに出せばよいでしょう.
注意点としては API が 返事を作れなかった場合は body.status2000 で 返ります. この場合に、応答を返さないで放置するか、自前で何かの応答を作りこむか判断ポイントになります. (ちなみに何も出力しないで放置バージョンを作ったら、ボットに話しかけたつもりで無視されたような形になり、寂しかったです…)

いざ、起動!

起動の仕方は、通常の Node.js の 起動に変わりありません. 今回は Slack トークン と A3RT Talk API KEY を 環境変数から受け取るようにしているので、その設定が必要です. 下記の REPLACE_THIS_WITH_YOUR_TOKEN を Slack ボット の トークンに、REPLACE_THIS_WITH_YOUR_APIKEY を A3RT Talk API の API KEY に 置き換えて実行します.

1
2
3
4
5
6
7
token=REPLACE_THIS_WITH_YOUR_TOKEN a3rt_talk_apikey=REPLACE_THIS_WITH_YOUR_APIKEY node index.js
Initializing Botkit v0.5.2
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.start
notice: ** BOT ID: bot ...attempting to connect to RTM!
notice: RTM websocket opened

※ Windows コマンドプロンプト の 場合は、下記のように set で 明示的に環境変数を設定してから実行します.

1
2
3
set token=REPLACE_THIS_WITH_YOUR_TOKEN
set a3rt_talk_apikey=REPLACE_THIS_WITH_YOUR_APIKEY
node index.js

トーク、トーク♪


Slack の 入力に対してちゃんと応答してくれました! 会話がかみ合っているような、そうでもないようなのは気にしないでおきましょう.



リクルートテクノロジーズさん が API を 公開してくださっているおかげで簡単に応答するボットを作ることができました. 登録もメールだけなので容易で助かります. クラウドサービスのサインアップとかになると大変なので、このぐらい手軽に使わせていただけるとうれしいですね. ほかの API も 試してみようっと.

Google Analytics に Search Console の 分析を追加する

このブログにアクセスしてくださる方々も増えてまいりました. ありがとうございます!
Google Analytics を 設置 していましたので、アクセスいただいている数値を知ることができますが、一番のアクセス元である検索エンジンから、どのような検索ワードで来てくださっているのかはわかりません. ということで、Google Search Console を 設置したいと思います. (今まで設定してなかったんかい…)

作業環境

  • Google Analytics
  • Google Search Console

Google Analytics から、Google Search Console の 設定

Google Analytics へ サインアップ&ログインしていることを前提に、Google Search Console の 設定をしたいと思います. まだサインアップしていない場合は、こちら を ご参照ください.

Google Analytics の ウェブサイトへアクセスし、左のメニュー から、[Search Console] - [ランディングページ] を クリックし、右のコンテンツから [Search Console の データ共有を設定] ボタンをクリックします.

各種設定のような画面が表示されますので 一番下 まで行き、[Search Console を 調整] ボタンをクリックします.

画面 一番上 まで行きます. (画面が書き換えられたのに、スクロール位置が固定されているようで一番下の何もない状態で描画されるので焦りました)
[Search Console の サイト] に ある [編集] の リンク を クリックします.

新しいタブ(or ウィンドウ) が 開き、Search Console の 連携画面が表示されます. [Search Console に サイトを追加] ボタン を クリックします.

さらに新しいタブが開き、Search Console の ようこそ画面が表示されます. ここにウェブサイトの URL を 入力し、[プロパティを追加] ボタンをクリックします.
今回は、これまでのブログ設置の流れから GitHub Pages に あるものとして https://[username].github.io/ と しました.

入力したウェブサイトの所有権があるかを確認されます. Google Analytics 連携しているので、推奨されている Google アナリティクス で 進めます. そのまま [確認] ボタンをクリックします.

確認が取れたこと表示されるので、[続行] リンクをクリックしして進めます.

Search Console の ダッシュボードへ戻ります.

これで、Google Search Console の 設定 が できました. Search Console として利用することはできるようになりましたが、Google Analytics で 一元的に見たいので、続いて Google Analytics との連携を進めます.

Google Analytics と Search Console の 連携設定

Search Console の 連携画面のタブに戻ります. ここで F5 キー もしくは、Ctrl + R を 押して画面をリロードします. そうすると、先ほど Google Search に 設定した URL が 表示されます.
追加した URL の ラジオボタンを選択し、[保存] ボタンをクリックします.

Google Analytics への関連付けを行ってよいかの確認ダイアログが表示されるので [OK] ボタンをクリックします.

これで、Google Analytics と Google Search の 連携が設定できました.

いざ確認!

さぁ Google Analytics に 戻り リロード! どのような検索ワードでいらっしゃってくださっているのか、いざ…
表示されるまで、2~3日かかるらしいです. はい.


無事、Search Console を 設置することができました.
結果は 2~3日ごとのことで、すぐに見れないのは残念ですが、まぁ そうですよね. もっと早くから設定しないとですね. いろいろ書いてみたいことが多くて、ブログ環境回りがついつい後回しになってしまいました…
とりあえず表示されるのを楽しみに待ちたいと思います.

Crystal Signal Pi on Docker

Raspberry Pi に 光り輝く四角柱 を 立てた Crystal Signal Pi、ようやくミドルウェアを導入しました. ミドルウェア を Docker の コンテナとして導入しましたので、φ(..)メモメモ.

作業環境

  • Raspberry Pi 3 Model B
  • Crystal Signal Pi
  • Docker

なぜ Docker ?

Raspbian Jessie Lite で Docker する - インストール編 の なぜ Docker ? で 書きました通り、ラズパイの環境に様々な SDK や ライブラリなどを混在させて競合が発生しないように、各環境を分離するためになります.

Crystal Signal Pi ミドルウェア は、Apache2 と Python2、そして pigpio に 依存しています. 依存関係が少ないので整理しやすいですが、他でまた Apache が 必要となったり、 Python3 を を 使い始めたら… と、思うとコンテナに分離しておけば環境もすっきりしますし、今後 Crystal Signal Pi を カスタマイズしようと思った際に、コンテナだったら Try & Error で 簡単に作り直しもできるのもよいです.

また、ちょっと他でラズパイが要りようになった際にも、コンテナを止めるだけで容易に転用できます. (もちろん、Crystal Signal Pi に 戻すのも簡単)

こんな考えから、Crystal Signal Pi on Docker で 作ることにしました.

ホスト側 OS に pigpio の 導入

Crystal Signal Pi は pigpio の サービス を 介して GPIO を 操作しています. そのため、pigpio を 導入する必要があります.
今回は Docker コンテナ として Crystal Signal Pi ミドルウェア を 導入しますが、pigpio は ラズパイ の GPIO 操作で共通的に使うものなので、コンテナではなく ホスト OS に 導入しました.

1
2
3
4
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install -y --no-install-recommends pigpio
pi@raspberrypi:~ $ sudo systemctl enable pigpiod.service
pi@raspberrypi:~ $ sudo systemctl restart pigpiod.service

Dockerfile の 作成

Crystal Signal Pi 用に、以下のような Dockerfile を 用意します.
ベースは軽量の armhf/alpine で、それに合わせてパッケージ管理を apk で 行います. apk を 2回に分けているのは、稼働時に必要となるパッケージ(curlapache2python) と ビルド時だけ必要なものを分離し、ビルド時だけに必要なものはコンテナ・イメージを小さくするため最後に apk del するためです. apk --virtual の オプションで追加(インストール) したものを疑似的にまとめることができ、削除する際に同じキーワードで削除できるのがいいですね.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pi@raspberrypi:~ $ nano Dockerfile
FROM armhf/alpine

RUN apk --no-cache upgrade \
&& apk add --no-cache curl apache2 python \
&& apk add --no-cache --virtual build-dependencies openssl rsync py2-pip gcc make python-dev musl-dev \
&& pip install --upgrade pip \
&& pip install pigpio \
\
&& curl -sSL https://raw.githubusercontent.com/azriton/crystal-signal-armhf-alpine/master/install.sh | sh \
\
&& apk del --purge build-dependencies \
&& rm -fr /tmp/* \
&& rm -fr /root/.cache \
;


EXPOSE 80
CMD /usr/sbin/httpd -f /etc/apache2/httpd.conf && /usr/local/bin/LEDController.py

上記 Dockerfile では、Crystal Signal Pi の ミドルウェアをインストールするスクリプト install.sh は、私の GitHub リポジトリから curl して実行しています. これは Docker コンテナで動かすためにスクリプトを一部修正してるものになります.
後々のアップデートに追随できなくなると困るので、完全な作り変えはせず、以下の方針で変更しある程度 diff が とれるようにしました. (どのくらい変えるかのバランスで悩んだ. こんな時はどうするのか、よい方法を知りたい)

  • OS と Python の パッケージ管理は Dockerfile へ 外部化する
  • 処理を実行させないものは削除する (コメントアウトにしない)

※ この Dockerfile も GitHub の リポジトリにアップしました.
https://github.com/azriton/crystal-signal-docker-armhf-alpine

ビルドする

Dockerfile が 用意できたら、docker build します.
--tag=repository/tag は 自身のリポジトリとタグを設定します.

1
pi@raspberrypi:~ $ docker build --force-rm --no-cache --tag=repository/tag .

実行!

Docker コンテナ の 実行は以下になります. --tag=repository/tag は ビルド時に指定したものと同じにします.

1
pi@raspberrypi:~ $ docker run -d -p 80:80 --net host --name crystal-signal-pi repository/tag

Crystal Signal Pi の 管理コンソールへブラウザでアクセスできるように -p 80:80 で 80番ポートを公開します.
--net host で コンテナからホスト側のネットワークスタックへアクセスできるようにします. これはホスト側に導入した pigpiod.service へ アクセスするためです.



Crystal Signal Pi

Raspberry Pi に 光り輝く四角柱 を 立てた Crystal Signal Pi、ついに Amazon.co.jp さん で 買えるようになりました! 実物を見ると輝く姿に圧倒されます. 監視用とのことですが、天気に合わせて色を変えたりと楽しめます.

Raspberry Pi 3

ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロRaspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.

Raspberry Pi 3 の 電源

Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.

マイクロ SD カード

ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


今回 armhf/alpine の コンテナを使ったことから、パッケージ管理のコマンドが異なったり、コンテナ内では systemd が 使えなかったりと、多少勝手が異なりましたが、何とか動かすことができました.
Docker 化 できたので、これで何も恐れることなく Try & Error できます. いざ、いろいろなシーンに合わせて光を変える挑戦へ!

花粉症対策 - 来年の自分へ宛てた手紙

ようやく花粉が少なくなってきた、気もしますが、まだまだヒノキにやられ花粉症のありとあらゆる症状が出て大変… 最近の薬はよくなってきたと聞くのですが故あって薬は使えないので、もうどうにもなりません orz
そんな中、新しい対策 グルタミン がかなり効いているので メモ & 毎年 対策に出遅れて困っている自分の来年へのメッセージ. 聞いた話、なんとなくやっていたことは忘れてしまうが、一生懸命書いたものは覚えていることを期待して.
※ あくまでも個人の所感・メモであり、症状の改善等を保証するものではありませんし、お体に合わないこともあり得ますので同様の方法を取られる場合は自己責任でお願いします. (個人のブログなので改めて書くことではないと思いますが…)

#1: 10月ごろから、毎日 “ヨーグルト” を 食べる

-- Azriton、キミはいつも出遅れているのだが、毎日ヨーグルトを食べることは花粉症対策として良い方法だ. 朝でも夜でもいい、とにかく 1日 1回ヨーグルトを食べるんだ. 種類は問わない食べやすいものを選び、継続することが大切だ. よく覚えておいて来年こそは冬が始まるころにはヨーグルトの日々を送ろう.

最近は機能性表示食品が増えてきました. 花粉症に効果があるとするヨーグルトも増えています. そういったものを選ぶのもよいでしょうし、食べやすい物でもよいでしょう. とにかく冬頃から継続的にヨーグルトを食べることで症状を抑えることができます.
この対策は半年ぐらい前から始める必要があるので、ついつい出遅れてしまったり、途中で止めてしまうのが難点だったりもします. とはいえ日々の食事と考えるとコスパは良いのかもしれません.

ちゃんと毎日ヨーグルトを食べていたころは 明治ブルガリアヨーグルト でした. 冷凍のブルーベリーなどを添えて. 春には自分でも驚くほど花粉症の効果がなかったことを覚えています. なんで続けられなかったかなぁ~

明治ブルガリアヨーグルトは花粉症対策をうたっていませんが、まず何よりも腸内環境を整えることが一番名だと思います. 最近では機能性表示食品で花粉症対策をうたっているものもあるので、そちらを選ぶのも手だと思います.

またヨーグルトメーカーを使うことで家庭でヨーグルトを作ることもできます. 最近は、だいぶ値段を抑えたメーカーも出てきたので、よりコスパを求めることができますね.

#2: 1月ごろから、”アレルケア”

-- Azriton、キミは また ヨーグルトのタイミングを逃したのだろう. しかたがない、年明けから始められる対策だ. カルピス健康通販のアレルケアだ. これなら錠剤のサプリだから、寝る前の水と一緒に飲める.

アレルケア「L-92乳酸菌」配合サプリ、こちらはアレルギーに効く乳酸菌をうたっています. もちろん、花粉症にも効果があるとのこと.
サプリとはいえ乳酸菌なので、こちらも中長期的な対策が必要です. 普段からサプリをとっている方は継続に問題ないかと思いますが、うっかりとか、めんどくさいとか…
これも効果を実感できたのに、なんで続けなかったかなぁ~ きっと当時はアマゾンで買えなかったら、ということにしておこう. ← 違う!

#3: 花粉を感じ始めたら、”アレルシャット 花粉イオンでブロック”

-- Azriton、キミは またしても対策を怠った. もう対処しかない. 花粉を感じ始めたら摂取しないようにブロックすることだ. 対処では何もしないよりはマシというレベルではあるだろうが… あと、マスクはするべきだ. どんなに嫌いでも!

対策を怠ってしまったら、もう対処しかない. 策は無いのだ…
ということで、マスクをして、眼鏡をして、とガードするしかないのですが、最近は付けないマスクということで、イオンでブロックできるらしいです.

花粉症は体内に入った花粉量が影響するのだとかで、とにかく体内に入れないこと. 少しでも感じ始めたらブロックするのが良いでしょう. イオンでどのくらいブロックできるのかわかりませんが、マスク嫌いで、どんなに花粉症がつらくてもマスクしない無謀な挑戦にも、何もしないよりはマシなぐらいには応えてくれました.

なお個人の所感ではありますが、スプレー式より、ポンプ式のが最後までしっかりつかえてよかったです. スプレー式はガスが抜けて最後まで使い切れなかった感(使い切ってたのかもしれませんが、缶を振るとシャプシャプして悔しかった)がありました.
ところで、花粉をブロックできるなら、インフルエンザとかも対処できるのかな?

#4: 出遅れて花粉症の症状に困ったら、”グリコのグルタミン”

-- Azriton、もうダメだ… 対策を忘れたキミに未来は無い…
が、Azriton、キミは新しい方法を入手した. そう グルタミン だ. 花粉症が発火してからの対処として使え、即効性もある. 今のところ最強の武器を手に入れたのだ. きっと来年も対策ができていないであろう、未来のキミに伝えるとしよう.

年々 対策を忘れ、そして悪化していく花粉症の中(って、悪化するなら対策すべきなのですが)、ほとほと困っているところを助けていただくツイートが!

藁をもすがる思いで アミノ酸プロスペック グルタミンパウダー を 購入. こちらは乳酸菌も入っているから、少しでも効用が増えることを期待して. そして、5g 飲んだところで、なんと 3分もしないうちにスッキリ! あれだけ困っていた花粉症の症状がおさまりました. 凄い!! (※ 個人の感想です)

3~5時間ぐらいで効果がなくなり元通りですが、十分な効果です. アミノ酸なので副作用もないのだとか. (各々の体質や、併せ呑みとかで影響も変わると思うので自己責任で)
どうしても効果が得られない日もありますが、格段に日常の過ごしやすさが変わりました. これは助かります. @bik__bo さん、ありがとうございます!

朝飲んでから出かけても、昼過ぎから夕方には効果が切れてしまうので、携帯が必要なので 薬包紙、パラピン を 買ってみました. 錠剤やカプセルを携帯するケースは売っているのですが、粉薬を携帯する商品ってなかなかない物ですね… 今回は “中: 105 x 105” を 買いましたが 5g だと、ちょっとギリギリな感じだったので、”大: 120 x 120” でもいいかもしれません.

薬包紙の折り方は こちら “説明図 薬包紙の折り方 - 薬包紙 - Wikipedia

その他

常に、”体を温めること”

体が冷えると症状が悪化する気がします. よく温めるとよいでしょう.

SAKE、”SAKE を 我慢” だ

-- Azriton、キミには無理な話だろう… だから、あえて語るまい. ただ、ひとつだけ言っておくと SAKE を 呑んだ後はグルタミンの効果は期待できない. それだけだ.


-- Azriton、未来のキミは花粉症対策ができているだろうか. それとも相も変わらず対処法を探しているのだろうか. 未来のキミが、この記事にたどりつけていることを祈り、そして花粉症に悩んでいないことを祈る.

ということで、文章として書いておけば、少しでも記憶に残っていて、将来の対策と対処に役に立っていることを期待して、ポスト.

同じ症状で困っている方、何かの役に立つ情報になれば幸いです. とはいえ医者でもなんでもないので、あくまでも ご参考程度&自己責任で見ていただければと.

Raspbian Jessie Lite で Docker する - GPIO on Alpine Linux 編

ラズパイ で Lチカ on Docker が できました が、よく考えたら コンテナ の OS は Raspbian でなくてもよかったのでは? ということで、Alpine Linux の コンテナから Lチカ してみたいと思います.

作業環境

  • Raspberry Pi 3 Model B
  • Raspbian Jessie Lite
  • Docker
  • Python 3.5

Alpine Linux とは?

Apine Linux は 軽量 の Linux ディストリビューションで、musl libcBusyBox で 作られた 軽量 の 組み込み向け Linux ディストリビューションとのことです.
Docker 界隈では注目を集めているようで、apk というパッケージ管理を持っていることから、BusyBox よりも扱いやすいとのことです.

どのくらい軽量化というと、前回利用させていただいた resin/rpi-raspbian と 比べると以下のように圧倒的に小さいです.

1
2
3
4
pi@raspberrypi:~ $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
armhf/alpine latest 3ddfeafc01f0 2 weeks ago 3.6 MB
resin/rpi-raspbian jessie-20170111 e49ffb0714c7 2 months ago 118 MB

Alpine コンテナ で Lチカ

さっそく armhf/alpine で コンテナを起動します. コマンドが若干違いますが、やりたいことに変わりは無いので難しくは無いですね.

1
2
3
4
5
6
7
8
9
pi@raspberrypi:~ $ docker run -it --rm --device /dev/gpiomem armhf/alpine /bin/sh
/ #
/ # apk update
/ # apk upgrade
/ # apk add python3 python3-dev musl-dev gcc
/ # pip3 install --upgrade pip
/ # pip3 install rpi.gpio
...(省略)
Successfully installed rpi.gpio-0.6.3

LEDを点滅させるプログラムを作成します. 前回と同じものになります.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/ # vi app.py
import RPi.GPIO as GPIO
import time

pin = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(pin, GPIO.OUT)

for _ in range(3):
GPIO.output(pin, GPIO.HIGH)
time.sleep(1.0)
GPIO.output(pin, GPIO.LOW)
time.sleep(1.0)

GPIO.cleanup()

プログラムを実行します.

1
/ # python3 app.py

Docker コンテナ から GPIO へ アクセスできました!(画像は前回のを拝借ですが、ちゃんと動きました.)


Raspberry Pi 電子工作キット

Lチカ こと、LED チカチカをはじめ、GPIO を 使った電子工作するためのキットです. いろいろなキットがありますが、こちらが一通りそろいつつコスパがよさそうです.

Raspberry Pi 3

ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロRaspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.

Raspberry Pi 3 の 電源

Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.

マイクロ SD カード

ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


ラズパイ の GPIO へ アクセスするとはいえ、よく考えたら Python から /dev/gpiomem へ アクセスしているだけで Raspbian 固有 の コマンドなりを使っているわけではなかったので、軽量のコンテナを使うべきでした.
今回、無事 Alpine Linux で Lチカ できたので、今後は Alpine Linux を 使っていこうと思います. あと、他のサーバサイド用途で
使っているコンテナも見直しだ…

Raspbian Jessie Lite で Docker する - GPIO 編

Raspberry で Docker が 動作した ので、続いては Docker の コンテナ側から GPIO を 使うプログラムを実行したいと思います.

作業環境

  • Raspberry Pi 3 Model B
  • Raspbian Jessie Lite
  • Docker
  • Python 3.4

Lチカ on Docker!

GPIO と 言ったら、とりあえず Lチカ(LED チカチカ) ですね.
前回から参考にさせていただいている記事 Make use of GPIO – Get Started with Docker 1.12 on Raspberry Pi に 説明があったので、そちらを使わせていただきたいと思います. そちらの配線図をもとに Raspberry Pi 3 で 以下のようなブレッドボード配線図にしました.

Raspbian コンテナ で Lチカ

Raspbian を 使おうと思ったのですが残念ながら、前回の armfh にはありませんでした. Resin.io で 作られいる Raspbian イメージがあるので、そちらを使うとのことです.

なお Resin.io は IoT デバイス を 管理するプラットフォームを提供しているサービスを提供しているようです. – Welcome to Resin.io

今回はお試しなので Dockerfile を 作らず、コンテナ内での作業で直接 Lチカ を 実行したいと思います.
まずは Raspbian Jessie で コンテナを起動します. GPIO に アクセスするためにはメモリの特定領域へ書き込める必要があります. そのため --device /dev/gpiomem オプションを付けます. (※ 参考にさせて頂いた記事では --privileged を 使っていますが、全デバイスへのアクセス権を与える必要はないので --device に しました)
※ 2017年3月現在、最新の latestjessiejessie-20170301jessie-20170329 は コンテナが立ち上がらず沈黙で終了するため jessie-20170111 を 使っています. いろいろ調べたけどわからんかった、悔しい orz

1
2
3
4
5
6
7
8
pi@raspberrypi:~ $ docker run -it --rm --device /dev/gpiomem resin/rpi-raspbian:jessie-20170111 /bin/bash
root@8e7c54acXXXX:/#
root@8e7c54acXXXX:/# apt-get update
root@8e7c54acXXXX:/# apt-get install -y --no-install-recommends python3-pip python3-dev gcc nano
root@8e7c54acXXXX:/# pip3 install rpi.gpio
...(省略)
Successfully installed rpi.gpio
Cleaning up...

LEDを点滅させるプログラムを作成します.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@8e7c54acXXXX:/# nano app.py
import RPi.GPIO as GPIO
import time

pin = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(pin, GPIO.OUT)

for _ in range(3):
GPIO.output(pin, GPIO.HIGH)
time.sleep(1.0)
GPIO.output(pin, GPIO.LOW)
time.sleep(1.0)

GPIO.cleanup()

プログラムを実行します.

1
root@8e7c54acXXXX:/# python3 app.py

Docker コンテナ から GPIO へ アクセスできました!

参考にさせて頂いた情報


Raspberry Pi 電子工作キット

Lチカ こと、LED チカチカをはじめ、GPIO を 使った電子工作するためのキットです. いろいろなキットがありますが、こちらが一通りそろいつつコスパがよさそうです.

Raspberry Pi 3

ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロRaspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.

Raspberry Pi 3 の 電源

Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.

マイクロ SD カード

ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


つたない知識をもとに Docker コンテナから GPIO へ アクセスを試みましたが、かなりハマった…

GPIO へのアクセスは “メモリへのアクセス” を 単純に考えていたので docker コマンドの引数に --device /dev/mem で 頑張ろうとしたのが間違えで、--privileged なら動くのに、--device /dev/mem は 動かない. いや、動くんだけど LED が 点灯しない. そして、ついには --cap-add SYS_RAWIO の 話を誤解したりと orz

本ポストにあるように --device /dev/gpiomem が 正しかったようです. 素直に ls -l /dev して、ながめれば、もっと早く気付いただろうに… 問題解決力をもっと鍛えねば.

Raspbian Jessie Lite で Docker する - インストール編

Raspberry の ベース環境が構築でき、いよいよ自作のアプリや検証などを始めたいところですが、アプリ等の動作環境に当たっては Docker を 使いたいと思います. まずは、その Docker が 動作する環境の構築と動作確認をします.

作業環境

  • Raspbian Jessie Lite
  • Docker

なぜ Docker ?

Docker は ホスト の Linux系 OS が 動作している環境に、コンテナと呼ばれる仮想環境でソフトウェアを動作できるようにする技術です. コンテナ型の仮想化 は、ざっくり言うと ホスト OS 上で隔離された環境(コンテナ)を作り出し、その隔離された環境で動かすソフトウェアなどは ホスト OS の プロセスとして実行される形態になります. そのため 完全な 別 OS の 実行環境を作るハイパーバイザー型の仮想化に対して軽量で動作させることができます.

では、なぜ ラズパイ で Docker を 使おうとしているのか. まずラズパイで GPIO の 実験をしたりだとか、クラウドと連携させて IoT デバイスのような実験をしたりといったことをしたいと考えています. その際に Python や Node.js など使ったり、そのライブラリ、クラウド の SDK に、Web サーバー など の ミドルウェア と 様々なソフトウェアを入れるということが考えられます.
また、その中でうまくいったものは稼働できるよに整理して残しつつ、また他の事をするといったことも考えられるでしょう.

もし、ここまで整理してきた Raspbian の 環境だけで行うとすると、環境がごちゃごちゃになってしまうでしょうし、時には 各種 SDK や ライブラリ の バージョンが競合して問題が発生するといったことも出てくるでしょう. そのために環境を切り替えられるようなライブラリを入れたり、ディレクトリ分けしたりといったこともできるかと思いますが、Docker のような コンテナに閉じ込めてしまえば、そのような問題の多くは解決できます.
また、うまくいって残しておきたいものは環境構築のためのファイル Dockerfile として残しておくこともできるので、外部公開や異なる環境 (ラズパイ上には限るでしょうが) に 移すことも容易になります.

今回は、このような考えから ラズパイ に Docker で アプリ や 検証環境を載せるようにしたいと考えました.

Docker の インストール と 起動実験

Docker comes to Raspberry Pi - Raspberry Pi に従って、Docker の サイトから Shell Script を 落として実行します. curl -sSL https://get.docker.com/ | sh だけで簡単にインストールできます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
pi@raspberrypi:~ $ curl -sSL https://get.docker.com/ | sh
...(省略)
+ sudo -E sh -c docker version
Client:
Version: 17.03.1-ce
API version: 1.27
Go version: go1.7.5
Git commit: c6d412e
Built: Fri Mar 24 00:19:15 2017
OS/Arch: linux/arm

Server:
Version: 17.03.1-ce
API version: 1.27 (minimum version 1.12)
Go version: go1.7.5
Git commit: c6d412e
Built: Fri Mar 24 00:19:15 2017
OS/Arch: linux/arm
Experimental: false

If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

sudo usermod -aG docker pi

Remember that you will have to log out and back in for this to take effect!

続いて、インストーラーのスクリプトの出力にあったように、ルートでない pi ユーザで Docker を 実行できるように pi ユーザ を docker グループに追加します. 出力にあったコマンドを、そのまま実行します. その後、デーモンの再起動では聞かないようなので sudo reboot します.

1
2
pi@raspberrypi:~ $ sudo usermod -aG docker pi
pi@raspberrypi:~ $ sudo reboot

コンテナ起動!

Docker は CPU の アーキテクチャ が ホスト と コンテナのイメージ で 同一である必要があります. そのため 2017年3月現在では Docker Hub に ある、ほとんどのイメージが x86_64 のため利用できません.

それでは困るのですが、Get Started with Docker 1.12 on Raspberry Pi の 記事によると、Docker チーム が armfh という prefix で 実験的なイメージを用意しているとのことです.
その記事に則り、Alpine Linux の イメージを使ってコンテナを起動してみたいと思います. オプションは -it-i の インタラクティブモード と -t の tty 接続になり コンテナ内に入って作業ができる状態になります. --rm で 終了時にコンテナを削除します. 後からコンテナにアクセスしたい場合は --rm は 外す必要があります.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pi@raspberrypi:~ $  docker run -it --rm armhf/alpine /bin/sh
Unable to find image 'armhf/alpine:latest' locally
latest: Pulling from armhf/alpine
7c863ad23cb7: Pull complete
Digest: sha256:d90337a24ddb9e72c44b84006cacd57205986a26a3384d6c68653adf2a0d62ba
Status: Downloaded newer image for armhf/alpine:latest

/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.5.2
PRETTY_NAME="Alpine Linux v3.5"
HOME_URL="http://alpinelinux.org"
BUG_REPORT_URL="http://bugs.alpinelinux.org"

/ # exit

参考にさせて頂いた情報


Raspberry Pi 3

ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロRaspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.

Raspberry Pi 3 の 電源

Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.

マイクロ SD カード

ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


Docker が Raspbian に 対応してくれていたおかげで簡単に動作させることができました. これで様々な環境を作っては壊すということができ、いろいろと試せそうです. 次はラズパイの魅力である GPIO を Docker の コンテナ側からちゃんと使えるかの確認です.