Visual Studio Code で git.exe が 見つからないと言われた場合の対処

Git for Windows Portable を インストールし Git が 使えるようになったのですが、最近 Visual Studio Code を アップデートしたら git.exe が 見つからないという警告が表示されるようになりました. 通常は出ないのでしょうが、 PortableGit を 使っている ので、そのあたりから警告が出たのでしょうか. 何にしろ対処したいと思います.

作業環境

  • Windows 10 64bit
  • Git for Windows Portable 64bit
  • Visual Studio Code

警告が発生している状況

まずは状況確認です.
Visual Studio Code, November 2017 (version 1.19) を 起動すると下図のような警告が表示されるようになりました. リリースノートには特に変更についての記載はないようなので不思議です…

git.exe への パスを確認しますが、通っているようです.

git.exe へのパスを設定

考えても仕方がないので、警告の文章でサジェストされている通り git.path の 設定をします.
ウィンドウ左下 の ⚙ 歯車 の アイコンをクリックし、[設定] を 選択します.

画面上部の検索ボックスへ git.path を 入力し、左側に git.path の 設定項目が出てきたら 設定項目の左 ✎ 鉛筆 アイコンをクリックして、右側のユーザー設定に追加します.
追加された設定項目値を git.exe までのパスに設定します. ディレクトリ区切りの \ 円マーク(バックスラッシュ) は \\ と 2回書いてエスケープするようにします.
今回は PortableGit for Windows 64bit の インストール で 設定したように C:\\Develop\\tool\\PortableGit\\cmd\\git.exe としました.

Visual Studio Code を 再起動すると、無事に警告が表示されなくなりました.


いろいろ探してみたのですが、結局何だったのかよくわかりませんでした. git.path の 設定項目自体も以前からある設定のようで、2017.12 とか関係なさそうですし. 何だったんだろう…
普段から git コマンドで操作しているので、あまり Visual Studio Code の Git 統合は使っていないから [今後は表示しない] でもよかったのかなと主思いますが Git 統合の機能がさらに良くなったら使うかもしれないので、パス設定にしました.

ラズパイ の 簡易スマート・スピーカー Google AIY で Voice Recognizer を 作る

この記事は「おうちハック Advent Calendar 2017」 13日目になります.
せっかくの Advent Calendar なので、何かネタをと思って考えてたのですが、うまく作れなかった… ので、Google AIY の キットを使っての話にしたいと思います.

作業環境

  • Raspberry Pi 3 Model B
  • Google AIY Voice Kit
  • GCP
  • Xming (必要に応じて)

最初は何を作りたかったのか

本題に入る前に、そもそも何を作ろうと思い、作れなかったのかについて少々. 作りたかったものはこれ、 Google AIYVoice Kit を ラズパイ・ゼロ で実現!です.

Voice Kit については、予約購入できたので 作って いました. (なかなか作業時間が取れず、ついに1ヶ月もかかってますが…)

その完成を目指すのもよいかと思ったのですが、同様のことがラズパイ・ゼロできたらコンパクトでよいと思い挑戦してました. なぜか Speaker pHat が 壊れてしまい、どうしても動作してくれないためタイムアウト. Voice Kit の 完成を目指すことにしました. 無念…

Google Home 簡易版ってだけでなく、下記のような面白いこともできそうだったのになぁと. いずれ再挑戦です!

Tomy Mr Money Google AIY Assistant | CIRCUITBEARD
https://circuitbeard.co.uk/2017/11/18/tomy-mr-money-google-aiy-assistant/

I turned a Furby into an Amazon Echo. Introducing: Furlexa - howchoo
https://howchoo.com/g/otewzwmwnzb/amazon-echo-furby-using-raspberry-pi-furlexa

Google AIY Voice Kit とは?

本題の Google AIY Voice Kit ですが、これは Raspberry Pi 3 と 組み合わせることで、簡易的なスマート・スピーカーを作ることができるキットです.
ラズパイなので、さらに自分で機能を追加できるので Google Home ではできない おうちハック が 目指せます! 例えばラズパイ・カメラをつけることもできます. ラズパイ本体の GPIO は Voice Hat で 埋まっていますが、Voice Hat に Servo を つけたりもできるようです.

品物は 例によって Pimoroni さん 始め、国内でも スイッチサイエンス さん や KSY さん で購入できます. (2017年12月現在、国内は品薄ですが)

また Raspberry Pi 3 (と マイクロ SD カード、電源) が 別途必要で、箱の中に入れるので ほぼ占有されます.
その他、工具としては小さいドライバ と 両面テープ が 必要となります.

必要なもの は ページの最後にまとめ たので、よろしければ ご確認ください.

国内の販売店さん は 日本語の説明書をつけてくれるようですが、Pimoroni さん で 購入した場合は 英語の冊子になります.
こちらの 公式 オンライン・ドキュメント と ほぼ同じで、写真がたくさんついているので英語が苦手でも作ることができるかと思います.

私の作成記はこちらになります.

今回は GCP(Google Cloud Platform) に 接続して、Voice Recognizer を 完成させます.

GCP への サインアップ と プロジェクトの作成

GCP の Cloud Console https://console.cloud.google.com/ へ アクセスします.
画面上部 [プロジェクトを選択] を クリックします.

プロジェクトの選択ダイアログが表示されるので、ダイアログ右上 [+] ボタンをクリックします.

新しいプロジェクト作成画面が表示されるのでプロジェクト名を入力し、[作成] を クリックします.
今回は voice-recognizer としました.

最初の画面に戻るので、画面上部 [プロジェクトを選択] を クリックしてプロジェクトの一覧を表示します.
作成したプロジェクトの名前をクリックします.

Google Assistant API の 有効化

左メニュー の [API と サービス] を クリックします.

画面中央上部 の [API と サービスの有効化] を クリックします.

API ライブラリが 表示されるので [API と サービスを検索] に assistant を 入力します.

Google Assistant API が 表示されるので、クリックします.

Google Assistant API の 詳細 が 表示されるので、[有効にする] を クリックします.

OAuth 2.0 の 設定

Google Assistant API の 画面で “認証情報が必要” と 警告されている通り、認証設定が必要となります.
左メニュー から [認証情報] を クリックします.

画面上側の [OAuth 同意画面] を 選択します.
これを設定しないと認証情報の作成時に警告され進めないので、あらかじめ作成しておきます.

最小限 [ユーザーに表示するサービス名] を 入力し、[保存] ボタンをクリックします.

認証情報の画面に戻るので、画面中央 [認証情報の作成] を クリックし、[OAuth クライアント ID] を 選択します.

クライアント ID の 作成画面が表示されるので、以下の情報を設定し、[作成] を クリックします.

  • アプリケーションの種類: その他
  • 名前: 任意の文字列 (今回は voice-recognizer と しました、クライアントだからホスト名のがよかったかな)

OAuth クライアント の 情報が表示されます.
この情報はファイルとしてダウンロードするので [OK] を クリックして進めます.

認証情報の一覧に先ほど作成した ID が あるので、右側の 下矢印 を クリックしてダウンロードします.
このファイルは後程使うのと、サービスにアクセスるための重要情報になるので大切に管理します.

Gooogle My Activity の 設定

アクティビティ管理 https://myaccount.google.com/activitycontrols へ アクセスし、以下の項目を有効化します.

  • ウェブとアプリのアクティビティ (Web and app activity)
  • 端末情報 (Device information)
  • 音声アクティビティ (Voice and audio activity)

Voice Kit の 設定

先ほど作成した認証情報のファイルを Voice Kit の /home/pi/assistant.json へ コピーします.
デモ・スクリプトが用意されているので起動します. デモは以下の3つです.

  • assistant_library_demo.py : 「おーけー ぐーぐる」の 音声に反応して起動し、会話をしてくれます
  • assistant_grpc_demo.py : Voice Kit の ボタンに反応して起動し、会話をしてくれます
  • cloud_speech_demo.py : Google Cloud Speech API を使って、独自のアプリを作るためのデモです

今回は 簡易 Google Home ということで、 assistant_library_demo.py を 起動します.
なお、最初に起動するときにブラウザが立ち上がり Google の OAuth を 行います. そのため Voice Kit に ディスプレイとキーボードをつなぐ必要があります. 今回は無かったので Xming で 代用しました.

また 公式 オンライン・ドキュメント の Using your device だと デスクトップ の [Start dev terminal] を ダブルクリックして、 src/assistant_library_demo.py を 実行するだけで起動するように書かれていますが、SSH 経由のためか ImportError: No module named 'google' エラーとなってしまいました. venv 環境に入れないとダメとのことで、こちらの Issues #133 executables breaking on ImportError after fresh clone on latest Raspbian Strech · Issue #133 · google/aiyprojects-raspbian に 上がっていました. 助かりました.

SSH から 以下のように実行しました.

1
pi@raspberry:~ $ cd ./AIY-voice-kit-python
2
pi@raspberry:~/AIY-voice-kit-python $ source env/bin/activate
3
(env) pi@raspberry:~/AIY-voice-kit-python $ src/assistant_library_demo.py
4
Say "OK, Google" then speak, or press Ctrl+C to quit...

実行するとブラウザが立ち上がり、Google 認証画面が表示されます.

先ほど設定した Google アカウントでサインインします.

OAuth で 認可を求められます. 先ほど設定した [Voice Recognizer] の 名前が表示され、Google アシスタントの利用許可が求められています. [許可] を クリックします.

認証フロー環境のめっせーが出るのでブラウザを閉じます.

あとは、「おーけー ぐーぐる」して話しかけて楽しみましょう!
ただし英語で orz

以上、おうちハック Advent Calendar 2017 13日目でした.


おうちハック Advent Calendar 2017 、いろいろな人のハックがあり、とても勉強になります.

明日 14日目 は @ponkio-oさん、「ラズパイとSuicaで玄関を開ける」とのこと。楽しみです!
2017.12.14 追記 14日目は @ponkio-o さん のところ、間違えて記載しておりました。訂正します。申し訳ありません。

2017.12.15 更新
前日 12日は、公開がないので、前々日 11日は @ksasao さん、Windows 10 でおうちハックする
「おうちハック」といういと、ついラズパイとか考えてしまうのですが、パソコンで慣れ親しんでる Windows 10!しかも 詫びデータ !! そして “あえて Windows - Windows 10 でおうちハックする“ です. 熱い!

後日 14日は、@ponkio-oさん、ラズパイとSuicaで玄関を開ける! スマートロックというんでしょうか、話は聞いたことがありますが、さすが「おうちハック」!自作するの勉強させていただきました!たしかに作れるんですよね!!

みんな、すごいなぁ!!


Google AIY Voice Kit に 必要なもの

Raspberry Pi 3

ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.

Raspberry Pi 3 の 電源

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

マイクロ SD カード

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

ドライバーセット

スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.

両面テープ

マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)

Google AIY

Google AIY Voice Kit そのもの. 一応載せておきますが 出始めなので Amazon.co.jp さん だと、高いですね. KSY さん 待ちでしょうか. Pimoroni さん は 2017年12月現在 在庫があるので £20.83 + 送料 £5.50 = 約4,000円です.
Pimoroni さん での お買い物方法は、こちら「Raspberry Pi Zero の 購入」も ご参照いただければ幸いです.


これで最近はやりのスマートスピーカーが我が家にもやってきました.
欲しいなぁと思っていたところではありましたが、やっぱり自分で作ったものがよかったので Google AIY の Voice Kit が 出てくれてとても嬉しいです.

今回は Google Home ならぬ Google Assist を 作りましたが、Amazon Echo ならぬ Amazon Alexa も ラズパイに入れられるので試してみたいところです.

スマスピ(?) で おうちハック を 加速させよう!

2017年 に 買ってよかったもの!

あっというやってきました師走. 年内にやりきることを整理しつつ、今年買ってよかったものを振り返りたいと思います.

🎮 スイッチ & スプラトゥーン2 で FPS 三昧!

たまたま Amazon.co.jp さん を 見ていたら、公式販売で買うことができました. ラッキー!
ほぼ Splatoon 2 (スプラトゥーン2) 専用機となっていますが、FPS が 大好きなので楽しいです♪

まだまだ品薄のようで定価での購入は難しいようですが、Amazon.co.jp さん では入荷次第、順次販売しているようなので定期的に以下のページを眺めるとよいかもしれません. (ページリロードを繰り返すというより、ゆっくりと定期的にという感じ. それで購入できました.)

🗑 ルンバ で お掃除レス!!

思い切って買って良かった. 床にものを置かないというルールが必要になりますが掃除がホントに楽になりました. 時短大事ですね!

💤 ベネクス で 快眠 & リカバリー

リカバリーウェアというジャンルのインナーです. こういうのってホントに効くの?って疑うタチですが相性が良かったのか、これを着て寝るとグッスリ眠れて疲れが取れます. 購入して登録をちゃんしたら割引クーポンも送ってくれました.
買い足し と VENEX リチャージロングタイツ メンズ インナー スパッツ にも手を出してみようと思っています.

🍻 ハイチオールC で 二日酔いもサヨナラ

「シミそばかす」な イメージのハイチオールですが、なんと!?実は二日酔いの症状にも効果があります!ちゃんと商品紹介にも効能にも書いてあります.
呑み会の前や後に飲んでおくと、ツライ二日酔いを防止することがで、いつも助けてもらっています. 頭痛系の症状が出る人は寝るときに アイスノンソフト などの氷枕系を併用するとさらに効果的! 常備薬です.

😆 グルタミン で 花粉症対策!

即効性で花粉症の症状を抑えることができる、それがグルタミン!花粉症シーズンはとても助かりました. そろそろ花粉症対策の準備を始めねば.

🍓 ラズパイ 🍓

最後の〆は やっぱり ラズパイ! 電子工作でいろいろと楽しむことができました. まだまだ色々なことに挑戦したいです.


買ったわけではないけど、欲しいもの!
年末のセールで駆け込み買うことができるかな!?

📺 局面ディスプレイ で 作業効率化

パソコンで作業する時には、やはり広い画面が欲しです. 4K だと かなり大きなパネルでないと小さくなってしまうので、なんのかんので 3K(という言葉ある?) ぐらいがちょうどよいです.
このディスプレイはウルトラワイドで局面になっているので、端のほうまで同じ感覚で見れるのだとか. ぜひ使ってみたいです.

😴 光のメトロノーム で 寝落ち

不眠というか寝つきが悪いので、この手の製品は新しいのが出るといろいろと気になります. 呼吸を整えて眠りへと誘導するのだとか. 上記ベネクスで安眠度は上がりましたが、寝つき改善は相変わらず欲しいところ. たぶん、私は何か考えてダメな気もするけど、欲しいというだけならタダなので…

MESH で 電子工作

基盤むき出しの電子工作もよいのですが、水回りに置きたいものだったり、コンパクトであったほしかったりといった時があります. そんな時に MESH があると自由度が上がるのかなぁと. ラズパイにも対応したみたいだし、遊んでみたい.


では、ハッピーホリデー & よいお年を.

Windows の プロキシ を 自動設定するタスクを作成

最近、利用するネットワーク環境が変えることが多くなり、プロキシ設定がめんどくさくなってきたのでスクリプトを作ってみました.

作業環境

  • Windows 10 64bit

プロキシ の 設定箇所

Windows で ブラウザなどを使う場合にプロキシを設定するのは [設定] - [ネットワークとインターネット] - [プロキシ] や、ブラウザのオプションから設定をします.
また、Node.js などは環境変数 HTTP_PROXYHTTPS_PROXY を 使うので、環境変数を設定します.
ブラウザだけではないので、ネットワークを切り替えプロキシの有無を変えたりするとなると、結構手間がかかります…

Windows の プロキシ設定を切り替えるためのツールはありそうだったのですが、環境変数の変更までとなると なかなか見つからず、簡単なスクリプトで済ませることにしました.

プロキシ の 自動設定スクリプト

今回は Windows 10 に 特別なものを入れないで動かしたいので、Windows PowerShell を 使うことにします.
ここでは configure-proxy.ps1 というファイル名で作成しました.

1
$PROXY_HOST="proxy.example.com"
2
$PROXY_PORT=8080
3
$LOCAL_ADDR="<local>"
4
5
$REG_KEY="HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"
6
7
try {
8
    $ignore = [System.Net.Dns]::GetHostAddresses(${PROXY_HOST}) | ? { $_.AddressFamily -eq "InterNetwork" }
9
10
    Set-ItemProperty -path ${REG_KEY} ProxyEnable -value 1
11
    Set-ItemProperty -path ${REG_KEY} ProxyServer -value "${PROXY_HOST}:${PROXY_PORT}"
12
    Set-ItemProperty -path ${REG_KEY} ProxyOverride -value ${LOCAL_ADDR}
13
    Set-Item -path env:HTTP_PROXY -value "http://${PROXY_HOST}:${PROXY_PORT}"
14
    Set-Item -path env:HTTPS_PROXY -value ${env:HTTP_PROXY}
15
    [Environment]::SetEnvironmentVariable("HTTP_PROXY", ${env:HTTP_PROXY}, [EnvironmentVariableTarget]::User)
16
    [Environment]::SetEnvironmentVariable("HTTPS_PROXY", ${env:HTTP_PROXY}, [EnvironmentVariableTarget]::User)
17
} catch {
18
    Set-ItemProperty -path ${REG_KEY} ProxyEnable -value 0
19
    Remove-Item -path env:HTTP_PROXY
20
    Remove-Item -path env:HTTPS_PROXY
21
    [Environment]::SetEnvironmentVariable("HTTP_PROXY", "", [EnvironmentVariableTarget]::User)
22
    [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "", [EnvironmentVariableTarget]::User)
23
}
24
25
$source=@"
26
[DllImport("wininet.dll")]
27
public static extern bool InternetSetOption(int hInternet, int dwOption, int lpBuffer, int dwBufferLength);
28
"@
29
$wininet = Add-Type -memberDefinition ${source} -passthru -name InternetSettings
30
${wininet}::InternetSetOption([IntPtr]::Zero, 95, [IntPtr]::Zero, 0)|out-null
31
${wininet}::InternetSetOption([IntPtr]::Zero, 37, [IntPtr]::Zero, 0)|out-null
32
33
exit 0

先頭の3行が設定部分になります.
$PROXY_HOST$PROXY_PORT に 利用する プロキシ・サーバ の ホスト名 と ポート番号を記述します.
$LOCAL_ADDR は “ローカル アドレスにはプロキシ サーバーを使用しない” に チェックする場合は <local> を いれます. また、”次で始まるアドレスにはプロキシを使用しない” に 値を入れる場合は、同じく $LOCAL_ADDR に セミコロン区切りで設定します. 例えば下記のようにします.
$LOCAL_ADDR="*.example.com;*.example.net;<local>"

8行目の GetHostAddresses(${PROXY_HOST}) で プロキシ・サーバ の IP アドレス を 引きます.
これは、現在のネットワークでプロキシ・サーバが引けるかを確認するためになります.
未使用変数 $ignore で 受けているのは、変数で受けないと DNS を 引いた情報が標準出力へ流れるのを防ぐためです.

IP アドレスが引けたら、後続の処理で以下を行いプロキシが利用できる設定をします.
コマンドラインからも呼べるように現在のセッションと永続化の両方の環境変数を設定しています.

  • レジストリ に プロキシの利用を有効化し、プロキシ・サーバの情報、ローカルや除外アドレスの設定
  • 現在のセッションにおける 環境変数 HTTP_PROXYHTTPS_PROXY を 設定
  • ユーザの環境変数 HTTP_PROXYHTTPS_PROXY を 設定

IP アドレスが引けなかった場合は catch ブロックへ処理が飛びます.
DNS で ルックアップできなかったので プロキシ・サーバ が 利用できないものとして、プロキシの設定を解除します.

  • レジストリ の プロキシ利用を無効化します (設定した値は残し、使わないものとしています)
  • 現在のセッションにおける 環境変数 HTTP_PROXYHTTPS_PROXY を クリア
  • ユーザの環境変数 HTTP_PROXYHTTPS_PROXY を クリア

最後にレジストリに設定したプロキシ情報をブラウザに反映するための処理を行います.
こちらの部分につきましては、下記の記事を参考にさせていただきました. ありがとうございます!

タスク スケジューラ から PowerShell を 実行する ラッパー・スクリプト

上記コマンドを必要に応じて実行することでプロキシ設定をだいぶ軽減できますが、やはり自動設定してくれるようにしたいところです.
そのために タスク スケジューラ を 使うのですが、タスク スケジューラ から PowerShell を 実行すると、コマンド プロンプト らしきものが 一瞬見えてしまいます. それを防ぐためにラッパーのスクリプトを作成します.
こちらは 「windows」で「PowerShell」を「一切画面表示せず」に「タスクスケジューラに登録」する方法を再確認 - Qiita さん の 情報を参考させていただきました. ありがとうございます!

ここでは ps-executer-for-task-scheduler.js というファイル名で作成しました.

1
shell = WScript.createObject("WScript.Shell");
2
ret = shell.Run("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoProfile -ExecutionPolicy RemoteSigned -File \"" + WScript.Arguments.Item(0) + "\"", 0, true);
3
WScript.Quit(ret);

powershell.exe を このスクリプトの引数で渡されたファイルで実行するというものになります.
-NoProfile -ExecutionPolicy RemoteSigned は スクリプトの実行ポリシーを一時的に下げるものになります. 今回は自分のスクリプトを実行することがわかっていますが、そうでない場合はよく確認してから実行する必要があります.
(と、これを見てくださっている方には 自分の スクリプト ではない ですね. ご確認ください…)

タスク スケジューラ に 設定

スタートメニュー で “タスク” で 検索すると、タスク スケジューラ が でてきます.

タスク スケジューラ ウィンドウ 右 の 操作 から、[タスクの作成] を クリックします. (“基本タスクの作成”ではないこと、注意です)

タスクの作成 の [全般]タブ で、タスクの名前を設定します. ここでは Configure Proxy としました.

[条件]タブ を 表示し、[電源] に ついているチェックを外します.
チェックがついていると外出時などでネットワーク構成が変わっているときなど、肝心な時に動作してくれなくなるので大事です.

[操作]タブ を 表示し、[新規] ボタンをクリックします.

[プログラム/スクリプト] に 先ほど作成した ラッパー・スクリプト ps-executer-for-task-scheduler.js を 指定します.
[引数の追加] に PowerShell 本体 の configure-proxy.ps1 を ダブルクォートで囲って入力します.
最後に、[開始] に スクリプトがあるディレクトリを入力します.
ここでは、C:\Temp\windows-proxy-config-task ディレクトリにスクリプトがにあるものとして設定しています.

入力できたら [OK] ボタンをクリックして戻ります.

[トリガー] タブ を 表示し、[新規] ボタンをクリックします. (ここから先は操作が重くなったり、処理に時間がかかったりすることがあります)

[タスクの開始] で イベント時 を 選択します.

設定を以下のように選択します.

  • [ログ] は Microsoft-Windows-NetworkProfile/Operational
  • [ソース] は NetworkProfile
  • [イベント ID] は 10000

詳細設定で、[遅延時間を指定する] を 念のため 1 秒間 に しておきます.
ネットワークが切り替わった後に発動するので問題ないはずですが、ちょっとだけ待ってから動かします.

設定したら OK を クリックします.

※ 上記で設定した イベント ID の 10000 は ネットワークに接続された場合に通知される ID に なります. ネットワーク切断時 は 10001 です. ソフトウェア で ネットワーク接続を切り替え、切断して元のネットワークに戻った場合にもタスクを実行したい、といったケースがある場合は、再度 [新規] を クリックして ID 10001 で 同じものを登録しておきます.

タスク スケジューラ の ウィンドウに戻ります.
ウィンドウ 左 から [タスク スケジューラ ライブラリ] を クリックすると、今回登録したタスクが表示されます.

ウィンドウ 中央 下段 から [履歴] タブを選択するとタスクのログが見れます.
まずは登録されたログが表示されています.

ネットワークを切り替え、ログのテーブル表示部分から 右クリック [最新の情報に更新] を すると、登録したタスクが実行されていることが確認できます.

リポジトリ

とりあえず、スクリプトだけ GitHub https://github.com/azriton/windows-proxy-config-task に アップしました.
README などは 追々書いていきたいと思います.



これでネットワークを切り替えた場合に、プロキシ設定が切り替わるようになりました!
ネットワークが切り替わったというイベントと、1秒の遅延設定をしているので、切り替わったと思う瞬間より少し遅れがある場合もありますが、十分使える範囲かと思います.

ラズパイ の 簡易スマート・スピーカー Google AIY の 初期セットアップ

Google AIY Voice Kit を 組み立てた ので、さっそく OS の イメージを焼き、初期設定をしたいと思います.

なお 前半 の “OS イメージ の 用意” と “SSH の 有効化 と Wi-Fi の 接続設定”、”スピーカー と マイク の 確認” 以外は、Google AIY Voice Kit とは、直接の関係はありません. ラズパイの基本的な設定をまとめたものになります.

今回は ディスプレイ や キーボード、マウス などが無い環境なので、SSH で セットアップしていきます.
ドキュメントによると カッコいいデスクトップが立ち上がるようですが見れないです. 残念.

ディスプレイなしなので CUI モードにすれば ラズパイ Zero W で も いけるかと思って1台組んでみたのですが、箱の切り欠きと配置が合わないのでケーブル類をちゃんと選ばないと収まらないのと、SD カード は 箱を開けないと抜き差しできなそうで、結局断念してラズパイ3を持ってかれました…

作業環境

  • Raspberry Pi 3 Model B
  • Google AIY Voice Kit

主な作業内容

これまで書いてきた記事から必要なものを集めて設定します. 関連する記事は下記になります.

OS イメージ の 用意

Google AIY プロジェクト の Voice Kit の ウェブサイトGet the Voice Kit SD Image から OS イメージをダウンロードします. ダウンロードしたファイルは aiyprojects-2017-09-11.img.xz でした.
※ 同梱の説明書には Get the Voice Kit SD Image への 短縮 URL https://magpi.cc/2x7JQfS が 記載されてました

.xz 形式は Windows の 標準装備では解凍できませんが、こちら ラズパイ の OS イメージを焼くときは Etcher が 便利 & UI カッコいい で 書きました Etcher は 解凍する必要なく直接 SD カード へ 書き込んでくれます. 便利だ!

ということで、Etcher を 起動し、上記ファイルを指定して、Flash します.

SSH の 有効化 と Wi-Fi の 接続設定

SD カード を 取り出す前に、SSH と Wi-Fi の 設定をしておきます.

エクスプローラー で SD カード の ドライブを表示し ssh ファイルを作成します. 空のファイルで大丈夫です.

同じく SD カードのドライブに wpa_supplicant.conf ファイルを作成します.

wpa_supplicant.conf ファイルの内容は以下で、 ssid と psk に 接続する Wi-Fi の 設定を記述します.
ファイルの改行コードは Windows の CRLF ではなく LF のため、メモ帳ではなく改行コードが設定できるエディタを使います.

1
country=JP
2
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
3
update_config=1
4
network={
5
        ssid="----Your-WiFi-SSID----"
6
        psk="----PLAIN-PASSPHRASE----"
7
}

※ ここでは psk が 平文となっていますが、起動後に接続して wpa_passphrase [SSID] [PASSPHRASE] コマンドを実行した結果の暗号化された psk に 置き換えておくとよいです.
またラズパイを よくセットアップする場合は 暗号化された psk で 作ったファイルをコピーしておいて、OS イメージを作った際にコピーできるようにしておくと便利です.

起動!

Google AIY Voice Kit の Raspberry Pi 3 に SD カードを差し、電源を投入します.

SSH で 接続

上記の Wi-Fi 設定ができていたら Wi-Fi 経由で SSH が つながるはずです. つながらなかったら 有線 LAN を つなぐか、ディスプレイ&キーボード…

Windows 10 は mDNS が 入っていて ホスト名.local で 接続を受け付けることはできるが、接続にはいけないらしい. なんでやねん!ってところですが、仕方がないので iTunesBonjour Print Services を インストールするか、頑張って IP アドレスから探しましょう.

SSH クライアント は Microsoft さん が 開発している Win32-OpenSSH を 使いました.

接続すると、ホスト鍵の確認があるので yes を 入力します.
続いてパスワードを聞かれるので、初期パスワード の raspberry を 入力します.

1
c:\> ssh pi@raspberrypi.local
2
The authenticity of host 'raspberrypi.local (fd91::3f13:2b1:fa24:XXXX)' can't be established.
3
ECDSA key fingerprint is SHA256:HDYEUoWS6x4RsD63mQgqbEdFsvnKyPBhT4forJCXXXX.
4
Are you sure you want to continue connecting (yes/no)? yes
5
Warning: Permanently added 'raspberrypi.local,fd91::3f13:2b1:fa24:XXXX' (ECDSA) to the list of known hosts.
6
pi@raspberrypi.local's password: [raspberry]

ログインできるとデフォルト・パスワードを変更するように警告が表示されます.
こちらは後に 公開鍵認証に変えておく と よいでしょう.

1
The programs included with the Debian GNU/Linux system are free software;
2
the exact distribution terms for each program are described in the
3
individual files in /usr/share/doc/*/copyright.
4
5
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
6
permitted by applicable law.
7
Build info: Tue Sep 12 00:36:20 UTC 2017 @ 3955cac
8
Last login: Mon Mar 19 14:40:39 2018 from 10.1.0.105
9
10
SSH is enabled and the default password for the 'pi' user has not been changed.
11
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

OS の バージョンなどを確認すると、Raspbian 8、Debian Jessie ベース であることが分かります.

1
pi@raspberrypi:~ $ cat /etc/issue
2
Raspbian GNU/Linux 8 \n \l
3
4
pi@raspberrypi:~ $ uname -a
5
Linux raspberrypi 4.9.35-v7+ #1014 SMP Fri Jun 30 14:47:43 BST 2017 armv7l GNU/Linux

スピーカー と マイク の 確認

説明書 P.38, 39 の STEP 09 Check speaker と STEP 10 check microphone では、デスクトップに配置されたアプリケーションを使って確認をしています.
※ オンライン・ドキュメントでは Verify it works

今回は SSH で 接続しているのでダブルクリックで実行できませんが、ホームディレクトリ の Desktop ディレクトリにあるアプリのファイルを確認すると Python スクリプトを実行していることがわかります. SSH から Python スクリプトを実行することで、同じことが確認できます.

1
pi@raspberrypi:~ $ ls -l /home/pi/Desktop/
2
合計 16
3
-rw-r--r-- 1 pi pi 214  9月 12 09:36 check_audio.desktop
4
-rw-r--r-- 1 pi pi 194  9月 12 09:36 check_cloud.desktop
5
-rw-r--r-- 1 pi pi 179  9月 12 09:36 check_wifi.desktop
6
-rw-r--r-- 1 pi pi 217  9月 12 05:50 dev_terminal.desktop
7
8
pi@raspberrypi:~ $ cat /home/pi/Desktop/check_audio.desktop 
9
[Desktop Entry]
10
Encoding=UTF-8
11
Type=Application
12
Name=Check audio
13
Comment=Check that the voiceHAT audio input and output are both working.
14
Exec=/home/pi/AIY-voice-kit-python/checkpoints/check_audio.py
15
Terminal=true

check_audio.py スクリプトを実行します.
実行パーミッションも立っていますし、スクリプト・ファイルの先頭行に #!/usr/bin/env python3 とあり Python で 実行できるようになっています. (そういえば この先頭行、 シバン って いうんですね)

1
pi@raspberrypi:~ $ /home/pi/AIY-voice-kit-python/checkpoints/check_audio.py

実行すると、正しくスピーカー が 接続できていると スピーカー から “Front, Center” と 音声が流れます.
正しく聞こえたら、 y を 入力して次へ進めます.

1
Playing a test sound...
2
Did you hear the test sound? (y/n) y

続いて、 When you're ready, press enter and say 'Testing, 1 2 3'... と 表示されるので、Enter キーを押してから “てすてぃんぐ わん、つー、すりー” って 話しかけます. いや、なんでも大丈夫ですが…
マイクを正しく接続できていれば、話しかけ時間3秒ぐらいで、すぐにスピーカーから話した内容が再生されます.
正しく聞こえたら、 y を 入力して次へ進めます.

1
When you're ready, press enter and say 'Testing, 1 2 3'...
2
Recording...
3
Playing back recorded audio...
4
Did you hear your own voice? (y/n) y

2回とも y でしたら、たぶん正しく動いているでしょうってことで、 Enter キー を 押下して終了します.

1
The audio seems to be working.
2
Press Enter to close...

ということで、初期セットアップ 完了です!


以下、Google AIY Voice Kit に直接は関係ないのですが、設定のまとめとして載せておきます. (主に自分用)

ホスト名 と ロケール&タイムゾーン を 設定

デフォルトのホスト名 raspberrypi は 他のラズパイを起動した際に被ると困るので必要に応じて変更しておきます. またロケールとタイムゾーンも併せておきます.
設定は sudo raspi-config コマンドを実行します.

ホスト名

  • 2 Hostname を 選択
  • 設定したいホスト名を入力し、 <Ok> を 選択

ロケール

  • 4 Localisation Options を 選択
  • I1 Change Locale を 選択
  • [*] en_GB.UTF-8 UTF-8 で スペースを押して * を 外す
  • [ ] ja_JP.UTF-8 UTF-8 で スペースを押して * を 付ける
  • <Ok> を 選択
  • Default locale for the system environment: と 聞かれるので、ja_JP.UTF-8 を 選択し <Ok>

タイムゾーン

  • 4 Localisation Options を 選択
  • I2 Change Timezone を 選択
  • AsiaTokyo と 選択

Wi-Fi の 国コード

  • 4 Localisation Options を 選択
  • I4 Change Wi-Fi Country を 選択
  • <Select> を 選択
  • JP Japan を 選択
  • <Ok> を 選択

最後に Finish を 選択し、再起動します.

パッケージ の アップデート

1
pi@raspberrypi:~ $ sudo apt-get update
2
pi@raspberrypi:~ $ sudo apt-get dist-upgrade -y

※ あまりに遅かったり、接続が悪いようでしたらミラー・サイトを設定します.
ミラー・サイトは こちら RaspbianMirrors - Raspbian から確認できます. JAIST を 例に以下のように設定します.

1
pi@raspberrypi:~ $ sudo nano /etc/apt/sources.list
2
# deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi
3
deb http://ftp.jaist.ac.jp/raspbian/ jessie main contrib non-free rpi

SSH と 公開鍵認証 の 設定

ざっと抜粋になります. 詳しくは Raspbian Jessie Lite の SSH/公開鍵認証 設定 を ご参照ください.

まずは Windows 側でキー・ペアを生成します.

1
c:\> ssh-keygen -t ed25519 -C ""
2
Generating public/private ed25519 key pair.
3
Enter file in which to save the key (C:\Users\[username]/.ssh/id_ed25519):
4
Enter passphrase (empty for no passphrase):
5
Enter same passphrase again:
6
Your identification has been saved in C:\Users\[username]/.ssh/id_ed25519.
7
Your public key has been saved in C:\Users\[username]/.ssh/id_ed25519.pub.
8
The key fingerprint is:
9
SHA256:T69X1O58qiKv7Sp/aPJTI+PpzUdOZDO+EcD5ldc8ON8
10
The key's randomart image is:
11
+--[ED25519 256]--+
12
|         . .  .o.|
13
|          +  oo.+|
14
|           o .ooo|
15
|            B ..E|
16
|        S .+ = . |
17
|        ooo.= . .|
18
|       . *.=.+ o |
19
|      o B+o.=   +|
20
|       B*OB+...XX|
21
+----[SHA256]-----+

続いて公開鍵を Raspberry Pi へ 送ります.

1
c:\> scp %USERPROFILE%\.ssh\id_ed25519.pub pi@raspberrypi.local:~
2
pi@raspberrypi.local's password: [PASSWORD]
3
id_ed25519.pub                     100%   83     0.1KB/s   00:00

Raspberry Pi 側で、ホーム・ディレクトリに所定のディレクトリとファイル配置をします.

1
pi@raspberrypi:~ $ mkdir ~/.ssh
2
pi@raspberrypi:~ $ chmod 700 ~/.ssh
3
pi@raspberrypi:~ $ cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
4
pi@raspberrypi:~ $ chmod 600 ~/.ssh/authorized_keys
5
pi@raspberrypi:~ $ rm -f ~/id_ed25519.pub

SSH サーバ で 公開鍵認証だけの設定にし、パスワード認証を禁止します.
sudo systemctl reload ssh した時の SSH 接続は残しておき、新しい SSH 接続で公開鍵認証が通ることを確認しておきます. 失敗すると作り直し or ディスプレイ/キーボードが必要 になるため注意が必要です.

1
pi@raspberrypi:~ $ sudo nano /etc/ssh/sshd_config
2
# Authentication:
3
PermitRootLogin no
4
RSAAuthentication no
5
6
# Change to no to disable tunnelled clear text passwords
7
PasswordAuthentication no
8
9
pi@raspberrypi:~ $ sudo systemctl reload ssh

最後に pi ユーザ の パスワードを削除します.

1
pi@raspberrypi:~ $ sudo passwd -d pi

Wi-Fi パワーマネジメント の 設定

Wi-Fi の パワーマネージメントによってネットワークアクセスが不安定になったり、遅延が生じるケースがあります. その場合は /etc/network/interfacesiface wlan0wireless-power off を 追加しておきます.

1
pi@raspberrypi:~ $ sudo nano /etc/network/interfaces
2
allow-hotplug wlan0
3
iface wlan0 inet manual
4
    wireless-power off
5
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

※ IP アドレスの固定化については、こちら 固定 IP アドレス を 設定する を ご参照ください.

SDカード の 延命化

あまり気にすることないとの情報もありますが、手間がかけられるようでしたらやっておいてもいいかもしれません.
やることがいろいろあるので、ここでは まとめた手順で記載します. 詳細は こちら Raspbian Jessie Lite の SDカード 延命化 を ご参照いただければ幸いです.

Swap 領域を削除し、テンポラリ領域 を RAM へ 配置します.

1
pi@raspberrypi:~ $ sudo apt-get purge -y --auto-remove dphys-swapfile
2
3
pi@raspberrypi:~ $ sudo nano /etc/fstab
4
tmpfs           /tmp            tmpfs   defaults,size=32m,noatime,mode=1777  0       0
5
tmpfs           /var/tmp        tmpfs   defaults,size=16m,noatime,mode=1777  0       0
6
tmpfs           /var/log        tmpfs   defaults,size=32m,noatime,mode=0755  0       0

起動時に /var/log の ディレクトリ構成を復元するようにスクリプトを配置します.
/etc/rc.localexit 0 の 前に 下記を追記します.

1
pi@raspberrypi:~ $ sudo nano /etc/rc.local
2
mkdir -p /var/log/apt
3
mkdir -p /var/log/fsck
4
mkdir -p /var/log/ntpstats
5
mkdir -p /var/log/samba
6
chmod 750 /var/log/samba
7
chown ntp:ntp /var/log/ntpstats
8
chown root:adm /var/log/samba

rsyslog の ログ出力を抑制します. 以下の部分をコメントアウトします.

1
pi@raspberrypi:~ $ sudo nano /etc/rsyslog.conf
2
#daemon.*                       -/var/log/daemon.log
3
#kern.*                         -/var/log/kern.log
4
#lpr.*                          -/var/log/lpr.log
5
#mail.*                         -/var/log/mail.log
6
#user.*                         -/var/log/user.log
7
#mail.info                      -/var/log/mail.info
8
#mail.warn                      -/var/log/mail.warn
9
#mail.err                       /var/log/mail.err
10
#news.crit                      /var/log/news/news.crit
11
#news.err                       /var/log/news/news.err
12
#news.notice                    -/var/log/news/news.notice
13
#*.=debug;\
14
#       auth,authpriv.none;\
15
#       news.none;mail.none     -/var/log/debug

RAM へ 配置したディレクトリを削除し、再起動します.

1
pi@raspberrypi:~ $ sudo rm -fr /tmp
2
pi@raspberrypi:~ $ sudo rm -fr /var/tmp
3
pi@raspberrypi:~ $ sudo rm -fr /var/swap
4
pi@raspberrypi:~ $ sudo reboot

ext4 ファイルシステム の ジャーナル を 無効化します.

1
pi@raspberrypi:~ $ sudo umount /dev/mmcblk0p2
2
pi@raspberrypi:~ $ sudo tune2fs -O ^has_journal /dev/mmcblk0p2
3
tune2fs 1.43.3 (04-Sep-2016)
4
The has_journal feature may only be cleared when the filesystem is
5
unmounted or mounted read-only.
6
7
pi@raspberrypi:~ $ sudo reboot

NTP に 日本のサーバを設定

1
pi@raspberrypi:~ $ sudo nano /etc/ntp.conf
2
#server 0.debian.pool.ntp.org iburst
3
#server 1.debian.pool.ntp.org iburst
4
#server 2.debian.pool.ntp.org iburst
5
#server 3.debian.pool.ntp.org iburst
6
server 0.jp.pool.ntp.org iburst
7
server 1.jp.pool.ntp.org iburst
8
server 2.jp.pool.ntp.org iburst
9
server 3.jp.pool.ntp.org iburst
10
11
pi@raspberrypi:~ $ sudo systemctl restart ntp

CPU の 動作クロック設定

通常は問題ないですが、常にハイ・パフォーマンスで動作させたり、省エネで動かす場合に設定します.
下記は常にハイ・パフォーマンスの例です. 詳しくは こちら CPU の 動作クロック設定 を ご参照ください.

1
pi@raspberrypi:~ $ sudo apt-get install cpufrequtils -y --no-install-recommends
2
pi@raspberrypi ~ $ sudo cpufreq-set -g performance
3
4
pi@raspberrypi:~ $ sudo cp /usr/share/doc/cpufrequtils/examples/cpufrequtils.sample /etc/default/cpufrequtils
5
pi@raspberrypi:~ $ sudo nano /etc/default/cpufrequtils
6
ENABLE="true"
7
GOVERNOR="performance"
8
MAX_SPEED=1200000
9
MIN_SPEED=600000

MAX_SPEEDMIN_SPEEDcat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies から出てきた数字を設定します. 上記は Raspberry Pi 3 の ものになります.

.bashrc の 設定

ここは完全にお好みなので、ご参考までに. (最小限の設定ですが)

1
pi@raspberrypi:~ $ nano ~/.bashrc
2
alias ls='ls --color=auto'
3
alias ll='ls --color=auto --format=verbose'
4
alias la='ls --color=auto --format=verbose --all'
5
alias cp='cp --interactive'
6
alias mv='mv --interactive'
7
alias rm='rm --interactive'
8
alias free='free -h'
9
alias grep='grep --color=auto'
10
11
pi@raspberrypi:~ $ source ~/.bashrc

基盤 の LED を 消灯する

基板上の ACT 緑 と PWR 赤 の LED が 気になる場合は消すことができます. 消してしまうと通電しているのかわからないという欠点もありますが、夜に赤く光らないので目に優しいかもしれません. led0 PWR で、led1 が ACT です.

1
pi@raspberrypi:~ $ echo 0 | sudo tee /sys/class/leds/led0/brightness
2
pi@raspberrypi:~ $ echo 0 | sudo tee /sys/class/leds/led1/brightness
3
4
pi@raspberrypi:~ $ echo "dtparam=act_led_trigger=none,act_led_activelow=on" | sudo tee -a /boot/config.txt
5
pi@raspberrypi:~ $ echo "dtparam=pwr_led_trigger=none,pwr_led_activelow=on" | sudo tee -a /boot/config.txt

最後にリブートしておく

必要はないと思いますが、いろいろ設定したのでリブートしておきます.

1
pi@raspberrypi:~ $ sudo reboot

Google AIY Voice Kit に 必要なもの

Raspberry Pi 3

ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.

Raspberry Pi 3 の 電源

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

マイクロ SD カード

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

ドライバーセット

スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.

両面テープ

マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)

Google AIY

Google AIY Voice Kit そのもの. 一応載せておきますが 出始めなので Amazon.co.jp さん だと、高いですね. KSY さん 待ちでしょうか. Pimoroni さん は 2017年11月現在 入荷待ちで £20.83 + 送料 £5.50 = 約4,000円です.
Pimoroni さん での お買い物方法は、こちら「Raspberry Pi Zero の 購入」も ご参照いただければ幸いです.


セットアップ系はコツコツ積み重ねてきたので記事が分散してしまったので、どこかで整理したいなぁ.

ラズパイ の OS イメージを焼くときは Etcher が 便利 & UI カッコいい

Google AIY Voice Kit を 組み立てた ので、OS の イメージを用意して起動、と行きたいところですが、OS イメージ を マイクロ SD に 焼く方法が気になったので確認と整理します.

作業環境

  • Windows 10 64 bit
  • Etcher for Windows x64
  • Raspberry Pi 3 Model B
  • Raspbian Jessie Lite
  • Google AIY Voice Kit

何があった?

Google AIY Voice Kit の 説明書 P. 34 からの Chapter Four / Set up the software で “Burn the image to a microSD card using a program like Etcher(etcher.io) on a Mac, Windows, or Linux computer.” という文章がありました.

また Web の リファレンス では Get the Voice Kit SD Image - Assembly Guide に “Write the image to an SD card using a card writing utility (Etcher.io is a popular tool for this)” とあり、 popular tool for this と 気になる記述もあります.

普段だったら使い慣れているソフトで サクッと SD カードを作ってしまうのですが、せっかく新しいことを始めているのだから、調べてみることにしました.

Etcher とは?

EtcherResin.io さん が OSS として開発しているツールで、トップエージに大きく “Burn. Better.” と 書かれている通り、SD カード や USB メモリ に OS イメージを安全で簡単に焼いてくれるツールです.
ところで CD ではないのに、なんで Burn、焼くんだろう…

Resin.io さん は、サービス自体は使ったことないのですが Raspbian Jessie Lite で Docker する 際にも、参考にさせていただいたりとお世話になっております. ありがとうございます.

Electron で できているので、Windows、Mac、Linux の クロス・プラットフォームで動作します.

そして何より素晴らしいのが、3ステップ完了できるということ.
img ファイルだけでなく、 zip などにも対応しているので、解凍するという作業無しで直接メディアを作ることができます.

Etcher は Raspbian 公式ドキュメント の INSTALLING OPERATING SYSTEM IMAGES や The MagPi の BURN SD CARDS WITH ETCHER などでも紹介されている方法になります.
※ なのに、なぜか INSTALLING OPERATING SYSTEM IMAGES USING WINDOWS へ 行って、Win32DiskImager を 使ってたんだよなぁ…

インストール

Etcher の ウェブサイト https://etcher.io/ へ アクセスします.
すでに OS を 判別してダウンロードボタンを作ってくれていますので、ボタンをクリックしてダウンロードします.

チェックサムは見つからなかったので確認できず. 残念.
ダウンロードしたファイルをダブルクリックしてインストーラを起動します.

ライセンスの確認が表示されるので、内容を確認し同意できるようだったら [同意する] ボタンをクリックして進めます. 同意できなかったら利用できません. キャンセルしましょう.

特に選択しなくインストールが進み、Etcher が 自動的に起動します.

イメージを焼く、前に設定をしておく

さっそく SD カード に Google AIY Voice Kit の イメージを焼きたいところですが、ちょっと設定をしておきます.
ウィンドウ右上、⚙ 歯車 の アイコンをクリックします.

設定が表示されるので、[Eject on success] の チェックを外します.
ここにチェックがついていると、イメージを焼いた後に SD カード の マウントを解除してしまうため、Raspbian の OS イメージを焼いた後に ssh ファイルを作成するのに、SD カードの入れ直しが必要になってしまうためです.
チェックを外したらウィドウ右上 [< Back] を クリックして戻ります.

ウィンドウ中段 の 左 [Select image] を クリックし、焼きたい OS イメージを選択します.
imgiso だけでなく、zip, bz2, dmg, dsk, etch, gz, hddimg, raw, rpi-sdimg, sdcard, xz などにも対応しています.
今回は aiyprojects-2017-09-11.img.xz を 選択しました. xz を 解凍する必要がないので助かります.

イメージを選択すると、フォーカス が ウィンドウ中段 の 右 [Flash!] に 移ります.
SD Card が 挿入済みのため、一気に [Flash!] へ 進み、事実上 2ステップです. 素晴らしい!
なお、ドライブが違う場合は ウィンドウ中央 の [Change] から変更できます.

用意ができたら [Flash!] を クリックし、焼きます.
ところで、なんでここは Burn じゃないんだろう…

しばらく待つと焼き終わります. フォーマット と 検証 も 自動的に行っておいてくれるので簡単です.
何よりこれ一つで終わりというのがいいですね.

Raspbian / Google AIY Voice Kit SD image の 初期ファイル配置

SD カード が 焼き終わったら、必要に応じて エクスプローラー で SD カード の ドライブを開き、初期ファイルを配置しておきます.

SSH 接続を許可する ssh ファイル

SSH で アクセスできるようにするには ssh というファイルを置いておく必要があります.
エクスプローラーの右クリック から [新規作成] を 選択し、適当なファイルを選択して、ファイル名を ssh に して作成します.
“拡張子を変更すると、ファイルが使えなくなる可能性があります。” と 警告表示されますが、今回は特に問題ないので [はい] を クリックします.

このあたりにつきましては、下記の記事も合わせてご参照いただければ幸いです.

Wi-Fi 設定 の wpa_supplicant.conf ファイル

Raspberry Pi 3 や Raspberry Pi Zero W を 使う場合は Wi-Fi が 利用できます.
あらかじめ wpa_supplicant.conf ファイルを用意しておくことで、起動時に 所定の場所である /etc/wpa_supplicant/wpa_supplicant.conf へ ファイルを移動し Wi-Fi へ 接続しておいてくれます.

ファイルの内容は以下で、 ssidpsk に 接続する Wi-Fi の 設定を記述します.
ファイルの改行コードは Windows の CRLF ではなく LF のため、メモ帳ではなく改行コードが設定できるエディタを使います.

1
country=JP
2
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
3
update_config=1
4
network={
5
        ssid="----Your-WiFi-SSID----"
6
        psk="----PLAIN-PASSPHRASE----"
7
}

このあたりにつきましては、下記の記事も合わせてご参照いただければ幸いです.


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 あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


いままでイメージをダウンロードしてから、解凍して、SDカードをフォーマット、焼き付けと手間がかかってましたが、Etcher の おかげで簡単に SD カードが作れるようになりました. 助かります.
今回はインストーラーで導入しましたが、ポータブル版もあるので開発環境セットとしてまとめおくのも手ですね.

公式サイト の Features に “Beautiful Interface - Who said burning SD cards has to be an eyesore.” とあるように、カッコいい UI だと思います. さすが IoT 管理プラットフォーム屋さんです.

ラズパイ の 簡易スマート・スピーカー Google AIY を 組み立てる

The MagPi Magazine 57号 の 付録だった Google AIY が Pimoroni さん で 先行予約が始まって1ヶ月、遂に届きました! さっそく組み立てます.

作業環境

  • Raspberry Pi 3 Model B
  • Google AIY Voice Kit

Google AIY Voice Kit とは?

Raspberry Pi 3 と 組み合わせることで、簡易的なスマート・スピーカーを作ることができるキットです.
Google の 音声認識を使って指示をさせることができるものになります. ちょうど Google Home が 発売され、Amazon Echo の 招待予約も開始され、スマート・スピーカーが熱い中に、DIY で 作れるキットとなります. さすがに、掛け声で起動とまではいかずボタン押してから話しかけるようですが. とはいえ、この辺はラズパイだからカスタマイズできそうです.

品物は The MagPi Magazine 57号 の 付録として配布されていましたが、すぐに売り切れてしまい、なかなか手に入らないものでした.
その後、単体で販売されることになり Pimoroni さん 始め、国内でも KSY さん が 販売します.

Raspberry Pi 3 (と マイクロ SD カード、電源) は 別途必要なので、手持ちがない場合は あらかじめ準備が必要です.
その他、工具としては小さいドライバ と 両面テープ が 必要となります.
HAT の 形になっているので簡単に取り外し可能ですが、箱の中に入っているので Raspberry Pi 3 は ほぼ占有と考えた方がいいかもしれません.

必要なもの は ページの最後にまとめ たので、よろしければ ご確認ください.

パッケージ と 付属物

まずはパッケージですが、思ったよりも大きいです. A4 より 一回り大きい感じで、A3 ぐらいでしょうか.
“Made by you with Google” が いいですね.

パッケージ背面です. 大きさの比較のために Raspberry Pi 3 を おきました. かなり大きいパッケージです.

付属物です. Raspberry Pi 3 は 入っていないので自前で用意が必要です.
説明書 と、AIY Voice HAT、スピーカー、ボタン、マイク、配線類、本体ケースの段ボール が 入っています.

説明書は英語なのですが、写真が豊富なので写真を参考にしながら作れそうです.
MagPi Magazine 57号 とは内容も、付属物も異なるのでデジタル版を確認する場合は MagPi Magazine 57号 PDF ではなく、こちらの Project サイト を 参照します.

Google AIY Voice Kit を 組み立てる

ラズパイ の GPIO ピン と 反対側 の 電源 や HDMI などがある側にスペーサーを付け、AIY Voice HAT を 装着します.
スペーサーが若干堅かったのでラズパイを折りそうで若干不安でした.

続いてスピーカーのケーブルを AIY Voice HAT の 青色のコネクタに接続します.
赤いケーブルがプラス(+) と 基盤にプリントされている側、黒いケーブルがマイナス(-) です. ぐっと差し込み、青いコネクタ上部にあるネジをしめます. ケーブルを引っ張っても抜けないぐらにしめます.

マイクのボードとボタンにつなげるコネクタを白のコネクタに接続します.
ピン数が4と5のコネクタなので迷わずにつなげることができます.

外箱 と 内部の仕切り の 段ボールを組み立てます.
ちょっと形が分かりにくいですが、こんな感じに収まります. ラズパイ3とスピーカーがちょうど収まります.
この辺は説明書の写真 を よく見ながら作ります. 折り目や順番が書かれていたりしますが、内部の仕切りが難しかったです. 少し先に進んで Put it all together か、下記写真のような組み込み後を確認しながら作りました.

箱詰めの際には マイクロ SD カードを抜いておきます. 差していると若干のはみだしがあり すんなり入らない感じでしたが、SD カードを外したら、わりとスムーズに入ってくれました.

ボタンを取り付けます. この後の敗戦で上下左右の確認があるので要注意desu. ボタン中央の灰色の部分に「宝」という漢字に王冠マークがあるのですが、その向きが分かるように取り付けます. (スマホだと「宝」が映らなかった、残念)
ボタンは青でしたが、パッケージや説明書では色が違うので箱によって違うのかな?

BUTTON というプリント と「宝」の漢字 が そろって読めるようにボタンを取り付けて、左上が白、右上が黒、左下が青、右下が赤 で ケーブルを接続します.
段ボールを折りそうだったので、いったん外して箱の外でケーブルをつなげました.

マイクのボードを両面テープでボタンの下に貼り付けて内部は完成です. ここでは両面テープがなかったので、箱の中に入れておきましたが、箱の天面の穴(写真だとボタン下の左右) に 基盤のマイク部分を揃えるように貼ります.

最後に蓋を閉じて、完成!

必要なもの

Raspberry Pi 3

ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.

Raspberry Pi 3 の 電源

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

マイクロ SD カード

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

ドライバーセット

スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.

両面テープ

マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)

Google AIY

Google AIY Voice Kit そのもの. 一応載せておきますが 出始めなので Amazon.co.jp さん だと、高いですね. KSY さん 待ちでしょうか. Pimoroni さん は 2017年11月現在 入荷待ちで £20.83 + 送料 £5.50 = 約4,000円です.
Pimoroni さん での お買い物方法は、こちら「Raspberry Pi Zero の 購入」も ご参照いただければ幸いです.


Google AIY Voice Kit の 組み立てができました. このままソフトウェアの設定に入りたいのですが、結構手間がかかりそうなので、今日はここまで.
こんな楽しそうなものを目の前に、寝れるかな (^^;

Serverlessconf Tokyo 2017 に 参加!!

Serverlessconf Tokyo 2017 に 参加もとい、出席しました. ブログを書くまでが #ServerlessConf、確かにですね. 今回、あまり参加できてなかったので内容の薄い感じがツラいですが、書くまでが勉強会! 頑張ります!!

Serverlessconf Tokyo 2017

いま自分の中で最も熱いアーキテクチャのサーバレース! そのグローバルなイベント Serverlessconf の 東京イベント が Serverlessconf Tokyo 2017.

2017年11月2日(木) ~ 3日(金) で 開催され、初日の 2日(木) は ワークショップで、サーバーレスのエキスパートたちとアプリ開発とか、話を聞いたりディスカスしたりできる時間. メイン は 3日(金)、多くのスピーカさんたちの話が聞けるイベントです.

なお、グローバル版 の ページは、こちら http://serverlessconf.io/. (今日現在だと、Tokyo は 2016 までしかないですね.)

この熱いイベント、参加するしかない!っす.
勉強させていただきます!!

ワークショップ と 会場

今回 ワークショップ が 一番参加できたのですが、ワークショップ の テーマは以下

  1. Serverless Tech Challenge with AWS Serverless Services
  2. Create A Trainable Bot as a Service with Azure Functions and Logic Apps
  3. Build your own serverless video sharing website with Lambda, API Gateway and Firebase
  4. Develop a Serverless Weatherbot with IBM Cloud Functions, Apache OpenWhisk and the Serverless Framework

普段は AWS を 使うことが多いので、1. の AWS Tech Challenge が 気になったのですが、Bot と Microsoft Bot Framework の キーワードにひかれて 2. の Azure を 選択しました. Azure も 使いこなせるようになってマルチ・クラウド使いへの入門に…

と、言うと前向きですが、若干 “Tech Challenge” の キーワードにビビッたところもあります (^^;
言い訳すると、有料セミナー の Tech Challenge とか、怖いじゃないですか…
とはいえ、Bot だけに限らず、 Azure に 興味があるのは事実です. GCP とかも手を広げたいところです.

会場は DMM.com Labo さん. 始めて伺いましたが、すごく素晴らしい場所です.
http://tokyo.serverlessconf.io/home.html#location

ウッディーな感じに、全方面に緑が配置された感じの場所で、写真奥のディスプレイ横には階段状のスペースにクッションなどもあります.
奥の左手にはカウンターのようなスペースがあり、コーヒーとかレンジが使える感じでした.

社員さんは、業務時間に自由に使えるとのことで「いいなぁ~~」が 止まりませんでした. いいなぁ~~!

Create A Trainable Bot as a Service with Azure Functions and Logic Apps

Bot ワークショップ の 内容は、チュートリアルに則って Bot アプリ作りです.

ワークショップ の マテリアルは、こちら.
マイクロソフトさん の 公式ブログでも公開されているので、大丈夫でしょう.
master ブランチ は 英語版で、日本語翻訳版は lang/jp ブランチです.
こちらの手順に則って、Azure Functions に ボットを作っていきます.
https://github.com/Azure-Samples/azure-serverless-workshop-team-assistant
https://github.com/Azure-Samples/azure-serverless-workshop-team-assistant/tree/lang/jp

説明がしっかり書かれているので、手順通りに進めれば大丈夫です!
ボット は スクワイアー(squire)さん、騎士の従者さんです.
まずは、ボット に 話しかけると槍(ランスのAA) を 渡してくれます、助かります、スクワイアーさん!

1
Here's your lance!
2
      mmm
3
     mmmmmmmmm
4
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
5
     mmmmmmmmm
6
     mmm

チュートリアルに従って、作っていけば大丈ぶ…
が、ハマった orz

やっぱ Azure 使い慣れていないってのが大きかったでしょうか.
あとマイクロソフトさんからアシストしてくれる方がたくさんいらっしゃったのですが、ちゃんと助けを求めなかったのがダメですね. セミナーとかではないのだから、ちゃんと助けを求めたり、いろいろ話をしないとですね.

なお、マイクロソフト の 中村 憲一郎さん が 解説を用意してくださりました.
ありがとうございます. こちらをもとに精進します.

Serverless Tech Challenge with AWS Serverless Services

ちょっと気になってた AWS テック・チャレンジ、お隣のスペースでやっていたので少しだけ拝見させていただきました.
テーマは下記から選択して、チーム開発するというものでした.
事前チームマッチングしていたようでしたが、メンバーの方が遅れていたのか「ひとりでマッチングサービス開発しましょう!」「いや、まずはチームのマッチングを~」みたいな話が聞こえて楽しそうでしたw

  • 掲示板
  • SNS
  • マッチング
  • Chat

優勝賞品は、なんと Amazon の ギフト券 10万円! すごいなぁ.
今度はちゃんと参加できるようにスキルを磨いておきたいところです.

Nov 3 / Conference

この時間がメイン、なのに諸事情により ざっと眺めて終了. 悔やまれます.
イベント会場ではマナーモード、ではなく 機内モードに ですね…
休日の呼び出しは控えるマナーが求められる昨今ですが、自衛も必要だ.

スポンサーさん の 出展ブースを回り、いろいろいただきました. ありがとうございます.

面白かったのは スカイアーチネットワークス サバカン 改め クラウド ラムダカレー! “美味なコード” が とても気になりますw
AWS Lambda に かけているので Lamb なのは仕方ないですが、やっぱり Rum の方が気になります. すみません.

マイクロソフトさん の フリスビー? と Flic ボタン.
丸い白いのがボタンで、押すと赤い LED が かすかに光ます.
スマホ・アプリと連動してなんか動くらしい…

えっと 一生懸命説明してくださったのですが、私が英語をわからないので… すみません.
こちらのツイートの カニオ さん に 説明頂いたのに.

てか、

“ってかなんか来場者さん皆デフォルトで英語理解できる人ばかりで凄い!さすが#serverlessTokyo”

orz、理解できるどころか、まともに聞こえてもいない人が単独でつまずいてたんですけどね…

カニオ さん、一生懸命説明してくださりありがとうございます!
この手の手バイスとか大好きなので、しっかり研究して楽しませていただきます!!



そんなこんなで、終わった Serverlessconf Tokyo 2017 でした.
もっとガッツリと話を聞きたかったんですが、生憎と帰還指示が発動され退散に. (ところで、この帰還指示はサーバーレスで発動されているのだろうか)

最近は資料を公開してくださっている発表者さんが多いので助かります.
しっかりと読みこなし、サーバーレスの熱いウェーブに乗っていけるように頑張ります.

そして、来年こそはテック・チャレンジに発表、何かちゃんと挑戦できるように準備をしておかないと.

最後とはなりますが、発表者さま、スポンサーさま、スタッフさま、みなさま、ステキなイベントをありがとうございます!!

C4 Labs で 買った ブレッドボード付きケース で Lチカする

C4 Labs さん で ヒートシンク付きケースを購入した際に、ブレッドボード付きケースも購入しました. これを組み立て Lチカ(LED チカチカ) したいと思います.
このケースは Raspberry Pi Zero と Zero W の どちらでも付けることができます. 今回はネットワークの取り回しが良くなる Raspberry Pi Zero W で 作ります.

作業環境

  • Raspberry Pi Zero W
  • Raspbian Jessie Lite

Raspberry Pi Zero に GPIO ピン を つける

さっそくケースの組み立てに入りたいところですが、Raspberry Pi Zero W は GPIO の ピンが立っていないモデルになります. GPIO の ピン が 無ければ、ブレッドボードがあっても使えないので、GPIO の ピンをつけます.

今回は Pimoroni さん の GPIO Hammer Header (Solderless) の Male を 使います.
Installation Jig を 取り付けて、ハンマーで叩くだけという優れもの!

Installation Jig の ピン用の溝がないプレート、溝のあるプレート、Raspberry Pi の 順に重ね、ガイド用のネジを通します.
GPIO Hammer Header の 穴のあるふくらみがある方を Raspberry Pi の GPIO ピン・ホール に 重ね、ハンマーで叩く天板をのせます.

そして、GPIO Hammer Header に のせた Installation Jig の 天板を思い切って、思い切ってハンマーでトントンします.
ちょっとドキドキしますが、それなりの力で叩かないと刺さりません.
いきなり強い力で叩くと割れかねませんが、徐々に力を強く加えていくことで、しっかりと刺さります.

プラスチックの土台まで、しっかり刺さったら Installation Jig を 外します.
Raspberry Pi Zero W に GPIO ピン が つきました.

ブレッドボード付きのケース を 組み立てる

GPIO ピン が ついたので、ブレッドボード付きのケース Zebra Zero Plus Breadboard in Wood for Raspberry Pi Zero 1.3 & Zero Wireless を組み立てます.
組み立て図がついており、各パーツの特徴もしっかりしているので組み立てやすいです.

ポイントがあるとしたら1つ、ブレッドボードの貼り付けはフレームを重ねてからのがよい、ということでしょうか. ブレッドボードに両面テープがついており貼り付けるのですが、フレームの大きさとかなりぴったりだったので、先に貼り付けるとフレームとかぶりかねません.

順番に重ねていき、天板をのせてネジ止め、そして完成!!
SD カードが取り外せるようになっているのがいいですね. これで色々なことが試せそうです.

Lチカ!

では定番の Lチカをやってみたいと思います.
Lチカは以前作った、 Raspbian Jessie Lite で Docker する - GPIO on Alpine Linux 編 の Docker 版 Lチカ を 使いました.

なお Raspberry Pi 基盤 の PWR LED が ケースのフレームにかぶり見えずらいので、電源を抜く際は注意が必要です.


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 あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.


今回、木のモデルを選びました. ピン番号などの文字が少し読みづらかったので Black Ice Case for Raspberry Pi Zero 1.3 and Zero Wireless の方がよかったかなぁと思ったりもしますが、木の雰囲気もオシャレなのでよしです.
それにしても GPIO Hammer Header、便利すぎる! 便利すぎます!!

reveal.js の 右下コントロール・ボタン を 公式デモっぽくする

reveal.js を 使って、Markdown で プレゼンテーション・スライド が 作れる ようになりました.
Markdown で 書くので デザインや多様な表現はできないことは承知しているのですが、右下にあるコントロール・ボタンでデザインが気になります. というこうとで、公式のオンライン・デモのコントロール・ボタンっぽくしてみたいと思います.
※ 以降「公式のオンライン・デモ」を「公式デモ」と表記します (ソースに demo.html があるので、ここまではオンラインをつけてましたが長いので

作業環境

  • Windows 10 64bit
  • reveal.js 3.5.0

デザインの違い と 作りたいものの確認

現在の状況について確認します.

まずは、自分で作成したスライドです. 右下のコントロール・ボタンは [ ▶ ] の ような形です.

続いて、公式デモのスライドです. 右下のコントロール・ボタンは [ > ] の ような形です.

この [ ▶ ]を、公式デモの [ > ] に したいというものになります.
あとは、最初のスライドと、下のスライドがある際に、コントロール・ボタンが少し動きます. スライドに動きがあると気になってしまうというのもありますが、ナビゲーションの観点から動いてもいいのかなぁと思います.

今回は、以下の3つを作ります

  • 右下のコントロール・ボタンを [ > ] の デザインにする
  • 最初のスライドはコントロール・ボタンがわずかに動く
  • 下のスライドがある場合は、コントロール・ボタン の [ V ] と [ > ] を わずかに動く

公式デモ の デザイン を 持ってくる

コントロール・ボタンのデザインについて、実は公式デモと配布版では CSS が 異なっています.
特に CONTROLS 以下は完全に違う状態で、これがデザインの [ ▶ ] と [ > ] の 違いになっています.

ということで、公式デモの CONTROLS 部分 の CSS を、自分のスライドの HTML <link> タグの下へ コピーします.

1
<style>
2
.reveal .controls {
3
  display: none;
4
  position: absolute;
5
  top: auto;
6
  bottom: 12px;
7
  right: 12px;
8
  left: auto;
9
  z-index: 1;
10
  color: #000;
11
  pointer-events: none;
12
  font-size: 10px; }
13
  .reveal .controls button {
14
    position: absolute;
15
    padding: 0;
16
    background-color: transparent;
17
    border: 0;
18
    outline: 0;
19
    cursor: pointer;
20
    color: currentColor;
21
    -webkit-transform: scale(0.9999);
22
            transform: scale(0.9999);
23
    transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease;
24
    transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
25
    z-index: 2;
26
    pointer-events: auto;
27
    font-size: inherit;
28
    visibility: hidden;
29
    opacity: 0;
30
    -webkit-appearance: none;
31
    -webkit-tap-highlight-color: transparent; }
32
  .reveal .controls .controls-arrow:before,
33
  .reveal .controls .controls-arrow:after {
34
    content: '';
35
    position: absolute;
36
    top: 0;
37
    left: 0;
38
    width: 2.6em;
39
    height: 0.5em;
40
    border-radius: 0.25em;
41
    background-color: currentColor;
42
    transition: all 0.15s ease, background-color 0.8s ease;
43
    -webkit-transform-origin: 0.2em 50%;
44
            transform-origin: 0.2em 50%;
45
    will-change: transform; }
46
  .reveal .controls .controls-arrow {
47
    position: relative;
48
    width: 3.6em;
49
    height: 3.6em; }
50
    .reveal .controls .controls-arrow:before {
51
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
52
              transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
53
    .reveal .controls .controls-arrow:after {
54
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
55
              transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
56
    .reveal .controls .controls-arrow:hover:before {
57
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg);
58
              transform: translateX(0.5em) translateY(1.55em) rotate(40deg); }
59
    .reveal .controls .controls-arrow:hover:after {
60
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg);
61
              transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); }
62
    .reveal .controls .controls-arrow:active:before {
63
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg);
64
              transform: translateX(0.5em) translateY(1.55em) rotate(36deg); }
65
    .reveal .controls .controls-arrow:active:after {
66
      -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg);
67
              transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); }
68
  .reveal .controls .navigate-left {
69
    right: 6.4em;
70
    bottom: 3.2em;
71
    -webkit-transform: translateX(-10px);
72
            transform: translateX(-10px); }
73
  .reveal .controls .navigate-right {
74
    right: 0;
75
    bottom: 3.2em;
76
    -webkit-transform: translateX(10px);
77
            transform: translateX(10px); }
78
    .reveal .controls .navigate-right .controls-arrow {
79
      -webkit-transform: rotate(180deg);
80
              transform: rotate(180deg); }
81
    .reveal .controls .navigate-right.highlight {
82
      -webkit-animation: bounce-right 2s 50 both ease-out;
83
              animation: bounce-right 2s 50 both ease-out; }
84
  .reveal .controls .navigate-up {
85
    right: 3.2em;
86
    bottom: 6.4em;
87
    -webkit-transform: translateY(-10px);
88
            transform: translateY(-10px); }
89
    .reveal .controls .navigate-up .controls-arrow {
90
      -webkit-transform: rotate(90deg);
91
              transform: rotate(90deg); }
92
  .reveal .controls .navigate-down {
93
    right: 3.2em;
94
    bottom: 0;
95
    -webkit-transform: translateY(10px);
96
            transform: translateY(10px); }
97
    .reveal .controls .navigate-down .controls-arrow {
98
      -webkit-transform: rotate(-90deg);
99
              transform: rotate(-90deg); }
100
    .reveal .controls .navigate-down.highlight {
101
      -webkit-animation: bounce-down 2s 50 both ease-out;
102
              animation: bounce-down 2s 50 both ease-out; }
103
  .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled,
104
  .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled {
105
    opacity: 0.3; }
106
    .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover,
107
    .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover {
108
      opacity: 1; }
109
  .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled,
110
  .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled {
111
    opacity: 0;
112
    visibility: hidden; }
113
  .reveal .controls .enabled {
114
    visibility: visible;
115
    opacity: 0.9;
116
    cursor: pointer;
117
    -webkit-transform: none;
118
            transform: none; }
119
  .reveal .controls .enabled.fragmented {
120
    opacity: 0.5; }
121
  .reveal .controls .enabled:hover,
122
  .reveal .controls .enabled.fragmented:hover {
123
    opacity: 1; }
124
125
.reveal:not(.has-vertical-slides) .controls .navigate-left {
126
  bottom: 1.4em;
127
  right: 6.4em; }
128
129
.reveal:not(.has-vertical-slides) .controls .navigate-right {
130
  bottom: 1.4em;
131
  right: 1.4em; }
132
133
.reveal:not(.has-horizontal-slides) .controls .navigate-up {
134
  right: 1.4em;
135
  bottom: 6.4em; }
136
137
.reveal:not(.has-horizontal-slides) .controls .navigate-down {
138
  right: 1.4em;
139
  bottom: 1.4em; }
140
141
.reveal.has-dark-background .controls {
142
  color: #fff; }
143
144
.reveal.has-light-background .controls {
145
  color: #000; }
146
147
.reveal.no-hover .controls .controls-arrow:hover:before,
148
.reveal.no-hover .controls .controls-arrow:active:before {
149
  -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
150
          transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
151
152
.reveal.no-hover .controls .controls-arrow:hover:after,
153
.reveal.no-hover .controls .controls-arrow:active:after {
154
  -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
155
          transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
156
157
@media screen and (min-width: 500px) {
158
  .reveal .controls[data-controls-layout="edges"] {
159
    top: 0;
160
    right: 0;
161
    bottom: 0;
162
    left: 0; }
163
  .reveal .controls[data-controls-layout="edges"] .navigate-left,
164
  .reveal .controls[data-controls-layout="edges"] .navigate-right,
165
  .reveal .controls[data-controls-layout="edges"] .navigate-up,
166
  .reveal .controls[data-controls-layout="edges"] .navigate-down {
167
    bottom: auto;
168
    right: auto; }
169
  .reveal .controls[data-controls-layout="edges"] .navigate-left {
170
    top: 50%;
171
    left: 8px; }
172
  .reveal .controls[data-controls-layout="edges"] .navigate-right {
173
    top: 50%;
174
    right: 8px; }
175
  .reveal .controls[data-controls-layout="edges"] .navigate-up {
176
    top: 8px;
177
    left: 50%; }
178
  .reveal .controls[data-controls-layout="edges"] .navigate-down {
179
    bottom: 8px;
180
    left: 50%; } }
181
</style>

スタイルを適用する要素を追加する

CSS を 持ってきただけでは、コントロール・ボタンは変化しません.
実は(実はが多い…)、コピーしたスタイル controls-arrow を 適用するためのタグが必要です. これも公式デモと JavaScript が 異なっている点になります.

さすがに reveal.js 本体を変更したくないですし、CDN からとってこれないのも困ります.
なのでイベント・フックを使って HTML が 生成された後に、必要となる要素を追加するようにしました.
以下のコードを HTML の <script> タグ にある、 Reveal.initialize({}); の 下に追加します.

1
<script>
2
Reveal.addEventListener('ready', (event) => {
3
    document.querySelector('aside.controls').dataset.controlsBackArrows = 'faded';
4
    Array.from(document.querySelectorAll('aside.controls > button'), e => {
5
        let child = document.createElement('div');
6
        child.setAttribute('class', 'controls-arrow');
7
        e.appendChild(child);
8
        e.style.color = 'rgb(66, 175, 250)';
9
    });
10
});
11
</script>

reveal.js で コンテンツの準備ができた ready イベントで、以下の処理をしています.

querySelector('aside.controls') で、コントロール・ボタンを保持しているコンテナの要素取得します.
データセット controlsBackArrowsfaded を 設定し、戻るボタン(左と上) に ボタンが薄くなるようなエフェクトをつけます.

querySelectorAll('aside.controls > button') で、すべてのコントロール・ボタンを取得します.
各ボタンの子要素に <div class="controls-arrow"></div> タグをを追加、このタグが先の CSS の 適用先になります.
そして、ボタンのスタイルに rgb(66, 175, 250) で カラーを設定します. ボタンの青のカラーが、上記 CSS の コピーでは上手く持ってこれないので、スタイル属性で適用しました.

これで、コントロール・ボタンのスタイルが公式デモのように [ > ] に なりました!
が、よくよくスライドを進めていくと、下スライドがある時に配置がずれてる…

配置を直し、ボタンを小さくする

どうも、元の [ ▶ ] の時に配置された CSS が 残っているようで、コピーしただけでは上書きできなかったようです.
再度 HTML に <style> を 追加して大きさと配置を修正します.

1
<style>
2
  .reveal .controls .controls-arrow:before, .reveal .controls .controls-arrow:after { width: 1.4em; }
3
  .reveal .controls .navigate-left,  .reveal:not(.has-vertical-slides) .controls .navigate-left  { top: 60px; left: 40px; }
4
  .reveal .controls .navigate-right, .reveal:not(.has-vertical-slides) .controls .navigate-right { top: 60px; left: 60px; }
5
  .reveal .controls .navigate-up,    .reveal:not(.has-vertical-slides) .controls .navigate-up    { top: 50px; left: 50px; }
6
  .reveal .controls .navigate-down,  .reveal:not(.has-vertical-slides) .controls .navigate-down  { top: 70px; left: 50px; }
7
</style>

.controls-arrow:after { width: 1.4em; } が ボタンの大きさになります.
その下の4つが、配置です. 大きさに合わせて配置を揃えていきます.

コンパクトになり、配置もそろいました!

最初のスライド と 下があるスライド の 場合は、少し動いてナビゲーションする

最初のスライドはよいとしても、メインのコンテンツ以外で動くものがあるのは、如何なものかとは思います. とはいえ縦方向にもスライドができるというは、あまりないのかなと思うと、ナビゲーションのために少し動いてもいいのかなと思い、公式デモから持ってきました.

まずは、少し動くアニメーションのスタイルです. 下矢印が動いて、戻るときに右矢印が動きます.
各%の数値を同じにすると、同時に動きます.

1
<style>
2
  @keyframes bounce-right {
3
    0%, 35%, 50%, 65%, 75% { transform: translateX(0); }
4
   45% { transform: translateX(2px); }
5
   55% { transform: translateX(-1px); } }
6
  @keyframes bounce-down {
7
    0%, 10%, 25%, 40%, 50% { transform: translateY(2px); }
8
   20% { transform: translateY(2px); }
9
   30% { transform: translateY(2px); } }
10
</style>

続いて、最初のスライド と 下があるスライド の 際にアニメーションさせる JavaScript を 作ります.
Reveal.addEventListener('ready', (event) => {}) は 上記ボタンの子要素を追加したときに記述した部分へ if(){} を 追記します.

1
<script>
2
    Reveal.addEventListener('ready', (event) => {
3
        if (Reveal.availableRoutes().right) { document.querySelector('.navigate-right').classList.add('highlight'); }
4
        if (Reveal.availableRoutes().down) { document.querySelector('.navigate-down').classList.add('highlight'); }
5
    });
6
7
    Reveal.addEventListener('slidechanged', (event) => {
8
        Array.from(document.querySelectorAll('aside.controls > button.highlight'), e => { e.classList.remove('highlight') });
9
10
        if (event.indexh === 0 && event.indexv ===0) {
11
          document.querySelector('.navigate-right').classList.add('highlight');
12
        }
13
14
        if (Reveal.availableRoutes().down) {
15
            document.querySelector('.navigate-down').classList.add('highlight');
16
            if (Reveal.availableRoutes().right) {
17
                document.querySelector('.navigate-right').classList.add('highlight');
18
            }
19
        }
20
    });
21
</script>

Reveal.addEventListener('ready', (event) => {}); で reveal.js の 描画が終わった後に、右矢印 と 下矢印 の それぞれが有効な場合に highlight の CSS クラスを適用します. Reveal.availableRoutes() で 指定する方向のスライドがあるかを判定できます.

Reveal.addEventListener('slidechanged', (event) => {}); では、スライドが変更された際のイベントで処理ができます.
まずは highlight を すべて解除します.

続いて indexhindexv0 、つまり最初のスライドの場合に、右矢印に highlight を 設定.

そして、下方向がある場合に下矢印に highlight し、さらに右方向がある場合は右矢印にも highlight を 設定します.

これで、完成になります.
キャプチャは、動きが小さすぎて変化が分かるのが取れませんでした.


マイクロソフト伝説マネジャーの 世界№1プレゼン術

日本マイクロソフト株式会社 の 澤さん の プレゼンに関する書籍です. マイクロソフトテクノロジーセンター の センター長 を 勤め、マイクロソフト社のエバンジェリストを率いられています.
こちらの書籍は、プレゼンのためのテクニックというよりも、なぜプレゼンをするのか、なぜプレゼンが必要なのかという点から書かれています. ここでの「プレゼン」は 大人数を前にしたようなプレゼンではなく、営業だとか、自分の考えを伝えるためだとかにも当てはまり、ビジネス・スキルとしても役立ちます.
プレゼンを作る際にはいつも読み返す、基本の立ち位置として重宝しています.

プレゼンの極意はマンガに学べ

漫画家の三田紀房さん の 書籍です. ドラゴン桜エンゼルバンク などが有名ですが、ビジネス関係の書籍も出されています.
こちらは、その中でもプレゼンに関する書籍で、プレゼンを一つの物語として考えてみようというものになります. 一般的なプレゼンの書籍とは一線を画すので、好みが分かれるところだと思います. ご自身の漫画を例に、どのようにスライドを作るのかについて書かれています.
プレゼンだけではなく、アイデアの練り方などにもふれているのがよく、たまに読み返しては様々なことに思いを巡らせたりしています.


デザイン・センスとか、スキルがないのに、どうしてもスライドのデザインとか気になってしまうんですよね… 絵が描けたりする人がうらやましいです.
今回は公式デモを真似するので、CSS を 上手く当てはめることでできましたが、JS や CSS 本体にデモ用の改変が入っていたので、HTML 側だけで合わせるのが難しかったです. 上手くできてよかった.