Git for Windows Portable を インストールし Git が 使えるようになったのですが、最近 Visual Studio Code を アップデートしたら git.exe
が 見つからないという警告が表示されるようになりました. 通常は出ないのでしょうが、 PortableGit を 使っている ので、そのあたりから警告が出たのでしょうか. 何にしろ対処したいと思います.
作業環境
まずは状況確認です.
Visual Studio Code, November 2017 (version 1.19) を 起動すると下図のような警告が表示されるようになりました. リリースノートには特に変更についての記載はないようなので不思議です…
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 統合の機能がさらに良くなったら使うかもしれないので、パス設定にしました.
この記事は「おうちハック Advent Calendar 2017」 13日目になります.
せっかくの Advent Calendar なので、何かネタをと思って考えてたのですが、うまく作れなかった… ので、Google AIY の キットを使っての話にしたいと思います.
作業環境
本題に入る前に、そもそも何を作ろうと思い、作れなかったのかについて少々. 作りたかったものはこれ、 Google AIY の Voice 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 ですが、これは 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 の Cloud Console https://console.cloud.google.com/ へ アクセスします.
画面上部 [プロジェクトを選択] を クリックします.
プロジェクトの選択ダイアログが表示されるので、ダイアログ右上 [+] ボタンをクリックします.
新しいプロジェクト作成画面が表示されるのでプロジェクト名を入力し、[作成] を クリックします.
今回は voice-recognizer としました.
最初の画面に戻るので、画面上部 [プロジェクトを選択] を クリックしてプロジェクトの一覧を表示します.
作成したプロジェクトの名前をクリックします.
左メニュー の [API と サービス] を クリックします.
画面中央上部 の [API と サービスの有効化] を クリックします.
API ライブラリが 表示されるので [API と サービスを検索] に assistant
を 入力します.
Google Assistant API が 表示されるので、クリックします.
Google Assistant API の 詳細 が 表示されるので、[有効にする] を クリックします.
Google Assistant API の 画面で “認証情報が必要” と 警告されている通り、認証設定が必要となります.
左メニュー から [認証情報] を クリックします.
画面上側の [OAuth 同意画面] を 選択します.
これを設定しないと認証情報の作成時に警告され進めないので、あらかじめ作成しておきます.
最小限 [ユーザーに表示するサービス名] を 入力し、[保存] ボタンをクリックします.
認証情報の画面に戻るので、画面中央 [認証情報の作成] を クリックし、[OAuth クライアント ID] を 選択します.
クライアント ID の 作成画面が表示されるので、以下の情報を設定し、[作成] を クリックします.
OAuth クライアント の 情報が表示されます.
この情報はファイルとしてダウンロードするので [OK] を クリックして進めます.
認証情報の一覧に先ほど作成した ID が あるので、右側の 下矢印 を クリックしてダウンロードします.
このファイルは後程使うのと、サービスにアクセスるための重要情報になるので大切に管理します.
アクティビティ管理 https://myaccount.google.com/activitycontrols へ アクセスし、以下の項目を有効化します.
先ほど作成した認証情報のファイルを 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
2
3
4pi@raspberry:~ $ cd ./AIY-voice-kit-python
pi@raspberry:~/AIY-voice-kit-python $ source env/bin/activate
(env) pi@raspberry:~/AIY-voice-kit-python $ src/assistant_library_demo.py
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で玄関を開ける! スマートロックというんでしょうか、話は聞いたことがありますが、さすが「おうちハック」!自作するの勉強させていただきました!たしかに作れるんですよね!!
みんな、すごいなぁ!!
ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.
マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)
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 も ラズパイに入れられるので試してみたいところです.
スマスピ(?) で おうちハック を 加速させよう!
]]>あっというやってきました師走. 年内にやりきることを整理しつつ、今年買ってよかったものを振り返りたいと思います.
たまたま Amazon.co.jp さん を 見ていたら、公式販売で買うことができました. ラッキー!
ほぼ Splatoon 2 (スプラトゥーン2) 専用機となっていますが、FPS が 大好きなので楽しいです♪
まだまだ品薄のようで定価での購入は難しいようですが、Amazon.co.jp さん では入荷次第、順次販売しているようなので定期的に以下のページを眺めるとよいかもしれません. (ページリロードを繰り返すというより、ゆっくりと定期的にという感じ. それで購入できました.)
思い切って買って良かった. 床にものを置かないというルールが必要になりますが掃除がホントに楽になりました. 時短大事ですね!
リカバリーウェアというジャンルのインナーです. こういうのってホントに効くの?って疑うタチですが相性が良かったのか、これを着て寝るとグッスリ眠れて疲れが取れます. 購入して登録をちゃんしたら割引クーポンも送ってくれました.
買い足し と VENEX リチャージロングタイツ メンズ インナー スパッツ にも手を出してみようと思っています.
「シミそばかす」な イメージのハイチオールですが、なんと!?実は二日酔いの症状にも効果があります!ちゃんと商品紹介にも効能にも書いてあります.
呑み会の前や後に飲んでおくと、ツライ二日酔いを防止することがで、いつも助けてもらっています. 頭痛系の症状が出る人は寝るときに アイスノンソフト などの氷枕系を併用するとさらに効果的! 常備薬です.
即効性で花粉症の症状を抑えることができる、それがグルタミン!花粉症シーズンはとても助かりました. そろそろ花粉症対策の準備を始めねば.
最後の〆は やっぱり ラズパイ! 電子工作でいろいろと楽しむことができました. まだまだ色々なことに挑戦したいです.
買ったわけではないけど、欲しいもの!
年末のセールで駆け込み買うことができるかな!?
パソコンで作業する時には、やはり広い画面が欲しです. 4K だと かなり大きなパネルでないと小さくなってしまうので、なんのかんので 3K(という言葉ある?) ぐらいがちょうどよいです.
このディスプレイはウルトラワイドで局面になっているので、端のほうまで同じ感覚で見れるのだとか. ぜひ使ってみたいです.
不眠というか寝つきが悪いので、この手の製品は新しいのが出るといろいろと気になります. 呼吸を整えて眠りへと誘導するのだとか. 上記ベネクスで安眠度は上がりましたが、寝つき改善は相変わらず欲しいところ. たぶん、私は何か考えてダメな気もするけど、欲しいというだけならタダなので…
基盤むき出しの電子工作もよいのですが、水回りに置きたいものだったり、コンパクトであったほしかったりといった時があります. そんな時に MESH があると自由度が上がるのかなぁと. ラズパイにも対応したみたいだし、遊んでみたい.
では、ハッピーホリデー & よいお年を.
]]>最近、利用するネットワーク環境が変えることが多くなり、プロキシ設定がめんどくさくなってきたのでスクリプトを作ってみました.
作業環境
Windows で ブラウザなどを使う場合にプロキシを設定するのは [設定] - [ネットワークとインターネット] - [プロキシ] や、ブラウザのオプションから設定をします.
また、Node.js などは環境変数 HTTP_PROXY
や HTTPS_PROXY
を 使うので、環境変数を設定します.
ブラウザだけではないので、ネットワークを切り替えプロキシの有無を変えたりするとなると、結構手間がかかります…
Windows の プロキシ設定を切り替えるためのツールはありそうだったのですが、環境変数の変更までとなると なかなか見つからず、簡単なスクリプトで済ませることにしました.
今回は Windows 10 に 特別なものを入れないで動かしたいので、Windows PowerShell を 使うことにします.
ここでは configure-proxy.ps1
というファイル名で作成しました.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
28
29
30
31
32
33$PROXY_HOST="proxy.example.com"
$PROXY_PORT=8080
$LOCAL_ADDR="<local>"
$REG_KEY="HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"
try {
$ignore = [System.Net.Dns]::GetHostAddresses(${PROXY_HOST}) | ? { $_.AddressFamily -eq "InterNetwork" }
Set-ItemProperty -path ${REG_KEY} ProxyEnable -value 1
Set-ItemProperty -path ${REG_KEY} ProxyServer -value "${PROXY_HOST}:${PROXY_PORT}"
Set-ItemProperty -path ${REG_KEY} ProxyOverride -value ${LOCAL_ADDR}
Set-Item -path env:HTTP_PROXY -value "http://${PROXY_HOST}:${PROXY_PORT}"
Set-Item -path env:HTTPS_PROXY -value ${env:HTTP_PROXY}
[Environment]::SetEnvironmentVariable("HTTP_PROXY", ${env:HTTP_PROXY}, [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("HTTPS_PROXY", ${env:HTTP_PROXY}, [EnvironmentVariableTarget]::User)
} catch {
Set-ItemProperty -path ${REG_KEY} ProxyEnable -value 0
Remove-Item -path env:HTTP_PROXY
Remove-Item -path env:HTTPS_PROXY
[Environment]::SetEnvironmentVariable("HTTP_PROXY", "", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("HTTPS_PROXY", "", [EnvironmentVariableTarget]::User)
}
$source=@"
[DllImport("wininet.dll")]
public static extern bool InternetSetOption(int hInternet, int dwOption, int lpBuffer, int dwBufferLength);
"@
$wininet = Add-Type -memberDefinition ${source} -passthru -name InternetSettings
${wininet}::InternetSetOption([IntPtr]::Zero, 95, [IntPtr]::Zero, 0)|out-null
${wininet}::InternetSetOption([IntPtr]::Zero, 37, [IntPtr]::Zero, 0)|out-null
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_PROXY
と HTTPS_PROXY
を 設定HTTP_PROXY
と HTTPS_PROXY
を 設定IP アドレスが引けなかった場合は catch
ブロックへ処理が飛びます.
DNS で ルックアップできなかったので プロキシ・サーバ が 利用できないものとして、プロキシの設定を解除します.
HTTP_PROXY
と HTTPS_PROXY
を クリアHTTP_PROXY
と HTTPS_PROXY
を クリア最後にレジストリに設定したプロキシ情報をブラウザに反映するための処理を行います.
こちらの部分につきましては、下記の記事を参考にさせていただきました. ありがとうございます!
上記コマンドを必要に応じて実行することでプロキシ設定をだいぶ軽減できますが、やはり自動設定してくれるようにしたいところです.
そのために タスク スケジューラ を 使うのですが、タスク スケジューラ から PowerShell を 実行すると、コマンド プロンプト らしきものが 一瞬見えてしまいます. それを防ぐためにラッパーのスクリプトを作成します.
こちらは 「windows」で「PowerShell」を「一切画面表示せず」に「タスクスケジューラに登録」する方法を再確認 - Qiita さん の 情報を参考させていただきました. ありがとうございます!
ここでは ps-executer-for-task-scheduler.js
というファイル名で作成しました.1
2
3shell = WScript.createObject("WScript.Shell");
ret = shell.Run("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoProfile -ExecutionPolicy RemoteSigned -File \"" + WScript.Arguments.Item(0) + "\"", 0, true);
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
10000
詳細設定で、[遅延時間を指定する] を 念のため 1 秒間
に しておきます.
ネットワークが切り替わった後に発動するので問題ないはずですが、ちょっとだけ待ってから動かします.
設定したら OK を クリックします.
※ 上記で設定した イベント ID の 10000
は ネットワークに接続された場合に通知される ID に なります. ネットワーク切断時 は 10001
です. ソフトウェア で ネットワーク接続を切り替え、切断して元のネットワークに戻った場合にもタスクを実行したい、といったケースがある場合は、再度 [新規] を クリックして ID 10001
で 同じものを登録しておきます.
タスク スケジューラ の ウィンドウに戻ります.
ウィンドウ 左 から [タスク スケジューラ ライブラリ] を クリックすると、今回登録したタスクが表示されます.
ウィンドウ 中央 下段 から [履歴] タブを選択するとタスクのログが見れます.
まずは登録されたログが表示されています.
ネットワークを切り替え、ログのテーブル表示部分から 右クリック [最新の情報に更新] を すると、登録したタスクが実行されていることが確認できます.
とりあえず、スクリプトだけ GitHub https://github.com/azriton/windows-proxy-config-task に アップしました.
README などは 追々書いていきたいと思います.
これでネットワークを切り替えた場合に、プロキシ設定が切り替わるようになりました!
ネットワークが切り替わったというイベントと、1秒の遅延設定をしているので、切り替わったと思う瞬間より少し遅れがある場合もありますが、十分使える範囲かと思います.
Google AIY Voice Kit を 組み立てた ので、さっそく OS の イメージを焼き、初期設定をしたいと思います.
なお 前半 の “OS イメージ の 用意” と “SSH の 有効化 と Wi-Fi の 接続設定”、”スピーカー と マイク の 確認” 以外は、Google AIY Voice Kit とは、直接の関係はありません. ラズパイの基本的な設定をまとめたものになります.
今回は ディスプレイ や キーボード、マウス などが無い環境なので、SSH で セットアップしていきます.
ドキュメントによると カッコいいデスクトップが立ち上がるようですが見れないです. 残念.
ディスプレイなしなので CUI モードにすれば ラズパイ Zero W で も いけるかと思って1台組んでみたのですが、箱の切り欠きと配置が合わないのでケーブル類をちゃんと選ばないと収まらないのと、SD カード は 箱を開けないと抜き差しできなそうで、結局断念してラズパイ3を持ってかれました…
作業環境
これまで書いてきた記事から必要なものを集めて設定します. 関連する記事は下記になります.
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 します.
SD カード を 取り出す前に、SSH と Wi-Fi の 設定をしておきます.
エクスプローラー で SD カード の ドライブを表示し ssh
ファイルを作成します. 空のファイルで大丈夫です.
同じく SD カードのドライブに wpa_supplicant.conf
ファイルを作成します.
wpa_supplicant.conf
ファイルの内容は以下で、 ssid と psk に 接続する Wi-Fi の 設定を記述します.
ファイルの改行コードは Windows の CRLF ではなく LF のため、メモ帳ではなく改行コードが設定できるエディタを使います.1
2
3
4
5
6
7country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="----Your-WiFi-SSID----"
psk="----PLAIN-PASSPHRASE----"
}
※ ここでは psk
が 平文となっていますが、起動後に接続して wpa_passphrase [SSID] [PASSPHRASE]
コマンドを実行した結果の暗号化された psk に 置き換えておくとよいです.
またラズパイを よくセットアップする場合は 暗号化された psk で 作ったファイルをコピーしておいて、OS イメージを作った際にコピーできるようにしておくと便利です.
Google AIY Voice Kit の Raspberry Pi 3 に SD カードを差し、電源を投入します.
上記の Wi-Fi 設定ができていたら Wi-Fi 経由で SSH が つながるはずです. つながらなかったら 有線 LAN を つなぐか、ディスプレイ&キーボード…
Windows 10 は mDNS が 入っていて ホスト名.local で 接続を受け付けることはできるが、接続にはいけないらしい. なんでやねん!ってところですが、仕方がないので iTunes か Bonjour Print Services を インストールするか、頑張って IP アドレスから探しましょう.
SSH クライアント は Microsoft さん が 開発している Win32-OpenSSH を 使いました.
接続すると、ホスト鍵の確認があるので yes
を 入力します.
続いてパスワードを聞かれるので、初期パスワード の raspberry
を 入力します.1
2
3
4
5
6c:\> ssh pi@raspberrypi.local
The authenticity of host 'raspberrypi.local (fd91::3f13:2b1:fa24:XXXX)' can't be established.
ECDSA key fingerprint is SHA256:HDYEUoWS6x4RsD63mQgqbEdFsvnKyPBhT4forJCXXXX.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'raspberrypi.local,fd91::3f13:2b1:fa24:XXXX' (ECDSA) to the list of known hosts.
pi@raspberrypi.local's password: [raspberry]
ログインできるとデフォルト・パスワードを変更するように警告が表示されます.
こちらは後に 公開鍵認証に変えておく と よいでしょう.1
2
3
4
5
6
7
8
9
10
11The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Build info: Tue Sep 12 00:36:20 UTC 2017 @ 3955cac
Last login: Mon Mar 19 14:40:39 2018 from 10.1.0.105
SSH is enabled and the default password for the 'pi' user has not been changed.
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
2
3
4
5pi@raspberrypi:~ $ cat /etc/issue
Raspbian GNU/Linux 8 \n \l
pi@raspberrypi:~ $ uname -a
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15pi@raspberrypi:~ $ ls -l /home/pi/Desktop/
合計 16
-rw-r--r-- 1 pi pi 214 9月 12 09:36 check_audio.desktop
-rw-r--r-- 1 pi pi 194 9月 12 09:36 check_cloud.desktop
-rw-r--r-- 1 pi pi 179 9月 12 09:36 check_wifi.desktop
-rw-r--r-- 1 pi pi 217 9月 12 05:50 dev_terminal.desktop
pi@raspberrypi:~ $ cat /home/pi/Desktop/check_audio.desktop
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=Check audio
Comment=Check that the voiceHAT audio input and output are both working.
Exec=/home/pi/AIY-voice-kit-python/checkpoints/check_audio.py
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
2Playing a test sound...
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
2
3
4When you're ready, press enter and say 'Testing, 1 2 3'...
Recording...
Playing back recorded audio...
Did you hear your own voice? (y/n) y
2回とも y
でしたら、たぶん正しく動いているでしょうってことで、 Enter キー を 押下して終了します.1
2The audio seems to be working.
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>
を 選択ja_JP.UTF-8
を 選択し <Ok>
タイムゾーン
4 Localisation Options
を 選択I2 Change Timezone
を 選択Asia
→ Tokyo
と 選択Wi-Fi の 国コード
4 Localisation Options
を 選択I4 Change Wi-Fi Country
を 選択<Select>
を 選択JP Japan
を 選択<Ok>
を 選択最後に Finish
を 選択し、再起動します.
1 | pi@raspberrypi:~ $ sudo apt-get update |
※ あまりに遅かったり、接続が悪いようでしたらミラー・サイトを設定します.
ミラー・サイトは こちら RaspbianMirrors - Raspbian から確認できます. JAIST を 例に以下のように設定します.1
2
3pi@raspberrypi:~ $ sudo nano /etc/apt/sources.list
deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi
deb http://ftp.jaist.ac.jp/raspbian/ jessie main contrib non-free rpi
ざっと抜粋になります. 詳しくは Raspbian Jessie Lite の SSH/公開鍵認証 設定 を ご参照ください.
まずは Windows 側でキー・ペアを生成します.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21c:\> ssh-keygen -t ed25519 -C ""
Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\[username]/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\[username]/.ssh/id_ed25519.
Your public key has been saved in C:\Users\[username]/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:T69X1O58qiKv7Sp/aPJTI+PpzUdOZDO+EcD5ldc8ON8
The key's randomart image is:
+--[ED25519 256]--+
| . . .o.|
| + oo.+|
| o .ooo|
| B ..E|
| S .+ = . |
| ooo.= . .|
| . *.=.+ o |
| o B+o.= +|
| B*OB+...XX|
+----[SHA256]-----+
続いて公開鍵を Raspberry Pi へ 送ります.1
2
3c:\> scp %USERPROFILE%\.ssh\id_ed25519.pub pi@raspberrypi.local:~
pi@raspberrypi.local's password: [PASSWORD]
id_ed25519.pub 100% 83 0.1KB/s 00:00
Raspberry Pi 側で、ホーム・ディレクトリに所定のディレクトリとファイル配置をします.1
2
3
4
5pi@raspberrypi:~ $ mkdir ~/.ssh
pi@raspberrypi:~ $ chmod 700 ~/.ssh
pi@raspberrypi:~ $ cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
pi@raspberrypi:~ $ chmod 600 ~/.ssh/authorized_keys
pi@raspberrypi:~ $ rm -f ~/id_ed25519.pub
SSH サーバ で 公開鍵認証だけの設定にし、パスワード認証を禁止します.sudo systemctl reload ssh
した時の SSH 接続は残しておき、新しい SSH 接続で公開鍵認証が通ることを確認しておきます. 失敗すると作り直し or ディスプレイ/キーボードが必要 になるため注意が必要です.1
2
3
4
5
6
7
8
9pi@raspberrypi:~ $ sudo nano /etc/ssh/sshd_config
Authentication:
PermitRootLogin no
RSAAuthentication no
Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
pi@raspberrypi:~ $ sudo systemctl reload ssh
最後に pi ユーザ の パスワードを削除します.1
pi@raspberrypi:~ $ sudo passwd -d pi
Wi-Fi の パワーマネージメントによってネットワークアクセスが不安定になったり、遅延が生じるケースがあります. その場合は /etc/network/interfaces
の iface wlan0
に wireless-power off
を 追加しておきます.1
2
3
4
5pi@raspberrypi:~ $ sudo nano /etc/network/interfaces
allow-hotplug wlan0
iface wlan0 inet manual
wireless-power off
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
※ IP アドレスの固定化については、こちら 固定 IP アドレス を 設定する を ご参照ください.
あまり気にすることないとの情報もありますが、手間がかけられるようでしたらやっておいてもいいかもしれません.
やることがいろいろあるので、ここでは まとめた手順で記載します. 詳細は こちら Raspbian Jessie Lite の SDカード 延命化 を ご参照いただければ幸いです.
Swap 領域を削除し、テンポラリ領域 を RAM へ 配置します.1
2
3
4
5
6pi@raspberrypi:~ $ sudo apt-get purge -y --auto-remove dphys-swapfile
pi@raspberrypi:~ $ sudo nano /etc/fstab
tmpfs /tmp tmpfs defaults,size=32m,noatime,mode=1777 0 0
tmpfs /var/tmp tmpfs defaults,size=16m,noatime,mode=1777 0 0
tmpfs /var/log tmpfs defaults,size=32m,noatime,mode=0755 0 0
起動時に /var/log
の ディレクトリ構成を復元するようにスクリプトを配置します./etc/rc.local
の exit 0
の 前に 下記を追記します.1
2
3
4
5
6
7
8pi@raspberrypi:~ $ sudo nano /etc/rc.local
mkdir -p /var/log/apt
mkdir -p /var/log/fsck
mkdir -p /var/log/ntpstats
mkdir -p /var/log/samba
chmod 750 /var/log/samba
chown ntp:ntp /var/log/ntpstats
chown root:adm /var/log/samba
rsyslog の ログ出力を抑制します. 以下の部分をコメントアウトします.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15pi@raspberrypi:~ $ sudo nano /etc/rsyslog.conf
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
lpr.* -/var/log/lpr.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
mail.info -/var/log/mail.info
mail.warn -/var/log/mail.warn
mail.err /var/log/mail.err
news.crit /var/log/news/news.crit
news.err /var/log/news/news.err
news.notice -/var/log/news/news.notice
*.=debug;\
auth,authpriv.none;\
news.none;mail.none -/var/log/debug
RAM へ 配置したディレクトリを削除し、再起動します.1
2
3
4pi@raspberrypi:~ $ sudo rm -fr /tmp
pi@raspberrypi:~ $ sudo rm -fr /var/tmp
pi@raspberrypi:~ $ sudo rm -fr /var/swap
pi@raspberrypi:~ $ sudo reboot
ext4 ファイルシステム の ジャーナル を 無効化します.1
2
3
4
5
6
7pi@raspberrypi:~ $ sudo umount /dev/mmcblk0p2
pi@raspberrypi:~ $ sudo tune2fs -O ^has_journal /dev/mmcblk0p2
tune2fs 1.43.3 (04-Sep-2016)
The has_journal feature may only be cleared when the filesystem is
unmounted or mounted read-only.
pi@raspberrypi:~ $ sudo reboot
1 | pi@raspberrypi:~ $ sudo nano /etc/ntp.conf |
通常は問題ないですが、常にハイ・パフォーマンスで動作させたり、省エネで動かす場合に設定します.
下記は常にハイ・パフォーマンスの例です. 詳しくは こちら CPU の 動作クロック設定 を ご参照ください.1
2
3
4
5
6
7
8
9pi@raspberrypi:~ $ sudo apt-get install cpufrequtils -y --no-install-recommends
pi@raspberrypi ~ $ sudo cpufreq-set -g performance
pi@raspberrypi:~ $ sudo cp /usr/share/doc/cpufrequtils/examples/cpufrequtils.sample /etc/default/cpufrequtils
pi@raspberrypi:~ $ sudo nano /etc/default/cpufrequtils
ENABLE="true"
GOVERNOR="performance"
MAX_SPEED=1200000
MIN_SPEED=600000
※ MAX_SPEED
と MIN_SPEED
は cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
から出てきた数字を設定します. 上記は Raspberry Pi 3 の ものになります.
ここは完全にお好みなので、ご参考までに. (最小限の設定ですが)1
2
3
4
5
6
7
8
9
10
11pi@raspberrypi:~ $ nano ~/.bashrc
alias ls='ls --color=auto'
alias ll='ls --color=auto --format=verbose'
alias la='ls --color=auto --format=verbose --all'
alias cp='cp --interactive'
alias mv='mv --interactive'
alias rm='rm --interactive'
alias free='free -h'
alias grep='grep --color=auto'
pi@raspberrypi:~ $ source ~/.bashrc
基板上の ACT 緑 と PWR 赤 の LED が 気になる場合は消すことができます. 消してしまうと通電しているのかわからないという欠点もありますが、夜に赤く光らないので目に優しいかもしれません. led0
PWR で、led1
が ACT です.1
2
3
4
5pi@raspberrypi:~ $ echo 0 | sudo tee /sys/class/leds/led0/brightness
pi@raspberrypi:~ $ echo 0 | sudo tee /sys/class/leds/led1/brightness
pi@raspberrypi:~ $ echo "dtparam=act_led_trigger=none,act_led_activelow=on" | sudo tee -a /boot/config.txt
pi@raspberrypi:~ $ echo "dtparam=pwr_led_trigger=none,pwr_led_activelow=on" | sudo tee -a /boot/config.txt
必要はないと思いますが、いろいろ設定したのでリブートしておきます.1
pi@raspberrypi:~ $ sudo reboot
ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.
マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)
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 を 組み立てた ので、OS の イメージを用意して起動、と行きたいところですが、OS イメージ を マイクロ SD に 焼く方法が気になったので確認と整理します.
作業環境
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 は Resin.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 イメージを選択します.img
や iso
だけでなく、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 じゃないんだろう…
しばらく待つと焼き終わります. フォーマット と 検証 も 自動的に行っておいてくれるので簡単です.
何よりこれ一つで終わりというのがいいですね.
SD カード が 焼き終わったら、必要に応じて エクスプローラー で SD カード の ドライブを開き、初期ファイルを配置しておきます.
SSH で アクセスできるようにするには ssh
というファイルを置いておく必要があります.
エクスプローラーの右クリック から [新規作成] を 選択し、適当なファイルを選択して、ファイル名を ssh
に して作成します.
“拡張子を変更すると、ファイルが使えなくなる可能性があります。” と 警告表示されますが、今回は特に問題ないので [はい] を クリックします.
このあたりにつきましては、下記の記事も合わせてご参照いただければ幸いです.
Raspberry Pi 3 や Raspberry Pi Zero W を 使う場合は Wi-Fi が 利用できます.
あらかじめ wpa_supplicant.conf
ファイルを用意しておくことで、起動時に 所定の場所である /etc/wpa_supplicant/wpa_supplicant.conf
へ ファイルを移動し Wi-Fi へ 接続しておいてくれます.
ファイルの内容は以下で、 ssid
と psk
に 接続する Wi-Fi の 設定を記述します.
ファイルの改行コードは Windows の CRLF
ではなく LF
のため、メモ帳ではなく改行コードが設定できるエディタを使います.1
2
3
4
5
6
7country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="----Your-WiFi-SSID----"
psk="----PLAIN-PASSPHRASE----"
}
このあたりにつきましては、下記の記事も合わせてご参照いただければ幸いです.
ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロ や Raspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
いままでイメージをダウンロードしてから、解凍して、SDカードをフォーマット、焼き付けと手間がかかってましたが、Etcher の おかげで簡単に SD カードが作れるようになりました. 助かります.
今回はインストーラーで導入しましたが、ポータブル版もあるので開発環境セットとしてまとめおくのも手ですね.
公式サイト の Features に “Beautiful Interface - Who said burning SD cards has to be an eyesore.” とあるように、カッコいい UI だと思います. さすが IoT 管理プラットフォーム屋さんです.
]]>The MagPi Magazine 57号 の 付録だった Google AIY が Pimoroni さん で 先行予約が始まって1ヶ月、遂に届きました! さっそく組み立てます.
作業環境
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 サイト を 参照します.
ラズパイ の GPIO ピン と 反対側 の 電源 や HDMI などがある側にスペーサーを付け、AIY Voice HAT を 装着します.
スペーサーが若干堅かったのでラズパイを折りそうで若干不安でした.
続いてスピーカーのケーブルを AIY Voice HAT の 青色のコネクタに接続します.
赤いケーブルがプラス(+) と 基盤にプリントされている側、黒いケーブルがマイナス(-) です. ぐっと差し込み、青いコネクタ上部にあるネジをしめます. ケーブルを引っ張っても抜けないぐらにしめます.
マイクのボードとボタンにつなげるコネクタを白のコネクタに接続します.
ピン数が4と5のコネクタなので迷わずにつなげることができます.
外箱 と 内部の仕切り の 段ボールを組み立てます.
ちょっと形が分かりにくいですが、こんな感じに収まります. ラズパイ3とスピーカーがちょうど収まります.
この辺は説明書の写真 を よく見ながら作ります. 折り目や順番が書かれていたりしますが、内部の仕切りが難しかったです. 少し先に進んで Put it all together か、下記写真のような組み込み後を確認しながら作りました.
箱詰めの際には マイクロ SD カードを抜いておきます. 差していると若干のはみだしがあり すんなり入らない感じでしたが、SD カードを外したら、わりとスムーズに入ってくれました.
ボタンを取り付けます. この後の敗戦で上下左右の確認があるので要注意desu. ボタン中央の灰色の部分に「宝」という漢字に王冠マークがあるのですが、その向きが分かるように取り付けます. (スマホだと「宝」が映らなかった、残念)
ボタンは青でしたが、パッケージや説明書では色が違うので箱によって違うのかな?
BUTTON というプリント と「宝」の漢字 が そろって読めるようにボタンを取り付けて、左上が白、右上が黒、左下が青、右下が赤 で ケーブルを接続します.
段ボールを折りそうだったので、いったん外して箱の外でケーブルをつなげました.
マイクのボードを両面テープでボタンの下に貼り付けて内部は完成です. ここでは両面テープがなかったので、箱の中に入れておきましたが、箱の天面の穴(写真だとボタン下の左右) に 基盤のマイク部分を揃えるように貼ります.
最後に蓋を閉じて、完成!
ラズパイがないと始められないので必要になります. 箱の中に入れてしまうので、ほぼ占有されます.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
スピーカー配線のコネクタをしめるのに使います. 細いドライバーであればなんでも大丈夫です.
マイクを箱の天板に貼り付けるのに使います. 持っていそうで意外となかったりも. (今回は無かった…)
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、確かにですね. 今回、あまり参加できてなかったので内容の薄い感じがツラいですが、書くまでが勉強会! 頑張ります!!
いま自分の中で最も熱いアーキテクチャのサーバレース! そのグローバルなイベント Serverlessconf の 東京イベント が Serverlessconf Tokyo 2017.
2017年11月2日(木) ~ 3日(金) で 開催され、初日の 2日(木) は ワークショップで、サーバーレスのエキスパートたちとアプリ開発とか、話を聞いたりディスカスしたりできる時間. メイン は 3日(金)、多くのスピーカさんたちの話が聞けるイベントです.
なお、グローバル版 の ページは、こちら http://serverlessconf.io/. (今日現在だと、Tokyo は 2016 までしかないですね.)
この熱いイベント、参加するしかない!っす.
勉強させていただきます!!
今回 ワークショップ が 一番参加できたのですが、ワークショップ の テーマは以下
普段は 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
ウッディーな感じに、全方面に緑が配置された感じの場所で、写真奥のディスプレイ横には階段状のスペースにクッションなどもあります.
奥の左手にはカウンターのようなスペースがあり、コーヒーとかレンジが使える感じでした.
社員さんは、業務時間に自由に使えるとのことで「いいなぁ~~」が 止まりませんでした. いいなぁ~~!
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
2
3
4
5
6Here's your lance!
mmm
mmmmmmmmm
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
mmmmmmmmm
mmm
チュートリアルに従って、作っていけば大丈ぶ…
が、ハマった orz
やっぱ Azure 使い慣れていないってのが大きかったでしょうか.
あとマイクロソフトさんからアシストしてくれる方がたくさんいらっしゃったのですが、ちゃんと助けを求めなかったのがダメですね. セミナーとかではないのだから、ちゃんと助けを求めたり、いろいろ話をしないとですね.
なお、マイクロソフト の 中村 憲一郎さん が 解説を用意してくださりました.
ありがとうございます. こちらをもとに精進します.
ちょっと気になってた AWS テック・チャレンジ、お隣のスペースでやっていたので少しだけ拝見させていただきました.
テーマは下記から選択して、チーム開発するというものでした.
事前チームマッチングしていたようでしたが、メンバーの方が遅れていたのか「ひとりでマッチングサービス開発しましょう!」「いや、まずはチームのマッチングを~」みたいな話が聞こえて楽しそうでしたw
優勝賞品は、なんと Amazon の ギフト券 10万円! すごいなぁ.
今度はちゃんと参加できるようにスキルを磨いておきたいところです.
この時間がメイン、なのに諸事情により ざっと眺めて終了. 悔やまれます.
イベント会場ではマナーモード、ではなく 機内モードに ですね…
休日の呼び出しは控えるマナーが求められる昨今ですが、自衛も必要だ.
スポンサーさん の 出展ブースを回り、いろいろいただきました. ありがとうございます.
面白かったのは スカイアーチネットワークス サバカン 改め クラウド ラムダカレー! “美味なコード” が とても気になりますw
AWS Lambda に かけているので Lamb
なのは仕方ないですが、やっぱり Rum
の方が気になります. すみません.
マイクロソフトさん の フリスビー? と Flic ボタン.
丸い白いのがボタンで、押すと赤い LED が かすかに光ます.
スマホ・アプリと連動してなんか動くらしい…
えっと 一生懸命説明してくださったのですが、私が英語をわからないので… すみません.
こちらのツイートの カニオ さん に 説明頂いたのに.
Microsoftブースで
— ちょまど@MS入社して20ヶ月 (@chomado) 2017年11月3日
Microsoft Azure (MSのクラウドサービス)と
Azure Functions (AWSでいうラムダ)
の説明をするカニオさん!
ってかなんか来場者さん皆デフォルトで英語理解できる人ばかりで凄い!さすが#serverlessTokyo pic.twitter.com/Lu1BoMC0xx
てか、
“ってかなんか来場者さん皆デフォルトで英語理解できる人ばかりで凄い!さすが#serverlessTokyo”
orz、理解できるどころか、まともに聞こえてもいない人が単独でつまずいてたんですけどね…
カニオ さん、一生懸命説明してくださりありがとうございます!
この手の手バイスとか大好きなので、しっかり研究して楽しませていただきます!!
そんなこんなで、終わった Serverlessconf Tokyo 2017 でした.
もっとガッツリと話を聞きたかったんですが、生憎と帰還指示が発動され退散に. (ところで、この帰還指示はサーバーレスで発動されているのだろうか)
最近は資料を公開してくださっている発表者さんが多いので助かります.
しっかりと読みこなし、サーバーレスの熱いウェーブに乗っていけるように頑張ります.
そして、来年こそはテック・チャレンジに発表、何かちゃんと挑戦できるように準備をしておかないと.
最後とはなりますが、発表者さま、スポンサーさま、スタッフさま、みなさま、ステキなイベントをありがとうございます!!
]]>C4 Labs さん で ヒートシンク付きケースを購入した際に、ブレッドボード付きケースも購入しました. これを組み立て Lチカ(LED チカチカ) したいと思います.
このケースは Raspberry Pi Zero と Zero W の どちらでも付けることができます. 今回はネットワークの取り回しが良くなる Raspberry Pi Zero W で 作ります.
作業環境
さっそくケースの組み立てに入りたいところですが、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チカは以前作った、 Raspbian Jessie Lite で Docker する - GPIO on Alpine Linux 編 の Docker 版 Lチカ を 使いました.
なお Raspberry Pi 基盤 の PWR LED が ケースのフレームにかぶり見えずらいので、電源を抜く際は注意が必要です.
Lチカ こと、LED チカチカをはじめ、GPIO を 使った電子工作するためのキットです. いろいろなキットがありますが、こちらが一通りそろいつつコスパがよさそうです.
ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロ や Raspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
今回、木のモデルを選びました. ピン番号などの文字が少し読みづらかったので Black Ice Case for Raspberry Pi Zero 1.3 and Zero Wireless の方がよかったかなぁと思ったりもしますが、木の雰囲気もオシャレなのでよしです.
それにしても GPIO Hammer Header、便利すぎる! 便利すぎます!!
reveal.js を 使って、Markdown で プレゼンテーション・スライド が 作れる ようになりました.
Markdown で 書くので デザインや多様な表現はできないことは承知しているのですが、右下にあるコントロール・ボタンでデザインが気になります. というこうとで、公式のオンライン・デモのコントロール・ボタンっぽくしてみたいと思います.
※ 以降「公式のオンライン・デモ」を「公式デモ」と表記します (ソースに demo.html
があるので、ここまではオンラインをつけてましたが長いので
作業環境
現在の状況について確認します.
まずは、自分で作成したスライドです. 右下のコントロール・ボタンは [ ▶ ] の ような形です.
続いて、公式デモのスライドです. 右下のコントロール・ボタンは [ > ] の ような形です.
この [ ▶ ]を、公式デモの [ > ] に したいというものになります.
あとは、最初のスライドと、下のスライドがある際に、コントロール・ボタンが少し動きます. スライドに動きがあると気になってしまうというのもありますが、ナビゲーションの観点から動いてもいいのかなぁと思います.
今回は、以下の3つを作ります
コントロール・ボタンのデザインについて、実は公式デモと配布版では CSS が 異なっています.
特に CONTROLS 以下は完全に違う状態で、これがデザインの [ ▶ ] と [ > ] の 違いになっています.
ということで、公式デモの CONTROLS
部分 の CSS を、自分のスライドの HTML <link>
タグの下へ コピーします.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181<style>
.reveal .controls {
display: none;
position: absolute;
top: auto;
bottom: 12px;
right: 12px;
left: auto;
z-index: 1;
color: #000;
pointer-events: none;
font-size: 10px; }
.reveal .controls button {
position: absolute;
padding: 0;
background-color: transparent;
border: 0;
outline: 0;
cursor: pointer;
color: currentColor;
-webkit-transform: scale(0.9999);
transform: scale(0.9999);
transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease;
transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
z-index: 2;
pointer-events: auto;
font-size: inherit;
visibility: hidden;
opacity: 0;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent; }
.reveal .controls .controls-arrow:before,
.reveal .controls .controls-arrow:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 2.6em;
height: 0.5em;
border-radius: 0.25em;
background-color: currentColor;
transition: all 0.15s ease, background-color 0.8s ease;
-webkit-transform-origin: 0.2em 50%;
transform-origin: 0.2em 50%;
will-change: transform; }
.reveal .controls .controls-arrow {
position: relative;
width: 3.6em;
height: 3.6em; }
.reveal .controls .controls-arrow:before {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
.reveal .controls .controls-arrow:after {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
.reveal .controls .controls-arrow:hover:before {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg);
transform: translateX(0.5em) translateY(1.55em) rotate(40deg); }
.reveal .controls .controls-arrow:hover:after {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg);
transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); }
.reveal .controls .controls-arrow:active:before {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg);
transform: translateX(0.5em) translateY(1.55em) rotate(36deg); }
.reveal .controls .controls-arrow:active:after {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg);
transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); }
.reveal .controls .navigate-left {
right: 6.4em;
bottom: 3.2em;
-webkit-transform: translateX(-10px);
transform: translateX(-10px); }
.reveal .controls .navigate-right {
right: 0;
bottom: 3.2em;
-webkit-transform: translateX(10px);
transform: translateX(10px); }
.reveal .controls .navigate-right .controls-arrow {
-webkit-transform: rotate(180deg);
transform: rotate(180deg); }
.reveal .controls .navigate-right.highlight {
-webkit-animation: bounce-right 2s 50 both ease-out;
animation: bounce-right 2s 50 both ease-out; }
.reveal .controls .navigate-up {
right: 3.2em;
bottom: 6.4em;
-webkit-transform: translateY(-10px);
transform: translateY(-10px); }
.reveal .controls .navigate-up .controls-arrow {
-webkit-transform: rotate(90deg);
transform: rotate(90deg); }
.reveal .controls .navigate-down {
right: 3.2em;
bottom: 0;
-webkit-transform: translateY(10px);
transform: translateY(10px); }
.reveal .controls .navigate-down .controls-arrow {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg); }
.reveal .controls .navigate-down.highlight {
-webkit-animation: bounce-down 2s 50 both ease-out;
animation: bounce-down 2s 50 both ease-out; }
.reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled,
.reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled {
opacity: 0.3; }
.reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover,
.reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover {
opacity: 1; }
.reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled,
.reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled {
opacity: 0;
visibility: hidden; }
.reveal .controls .enabled {
visibility: visible;
opacity: 0.9;
cursor: pointer;
-webkit-transform: none;
transform: none; }
.reveal .controls .enabled.fragmented {
opacity: 0.5; }
.reveal .controls .enabled:hover,
.reveal .controls .enabled.fragmented:hover {
opacity: 1; }
.reveal:not(.has-vertical-slides) .controls .navigate-left {
bottom: 1.4em;
right: 6.4em; }
.reveal:not(.has-vertical-slides) .controls .navigate-right {
bottom: 1.4em;
right: 1.4em; }
.reveal:not(.has-horizontal-slides) .controls .navigate-up {
right: 1.4em;
bottom: 6.4em; }
.reveal:not(.has-horizontal-slides) .controls .navigate-down {
right: 1.4em;
bottom: 1.4em; }
.reveal.has-dark-background .controls {
color: #fff; }
.reveal.has-light-background .controls {
color: #000; }
.reveal.no-hover .controls .controls-arrow:hover:before,
.reveal.no-hover .controls .controls-arrow:active:before {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
.reveal.no-hover .controls .controls-arrow:hover:after,
.reveal.no-hover .controls .controls-arrow:active:after {
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
@media screen and (min-width: 500px) {
.reveal .controls[data-controls-layout="edges"] {
top: 0;
right: 0;
bottom: 0;
left: 0; }
.reveal .controls[data-controls-layout="edges"] .navigate-left,
.reveal .controls[data-controls-layout="edges"] .navigate-right,
.reveal .controls[data-controls-layout="edges"] .navigate-up,
.reveal .controls[data-controls-layout="edges"] .navigate-down {
bottom: auto;
right: auto; }
.reveal .controls[data-controls-layout="edges"] .navigate-left {
top: 50%;
left: 8px; }
.reveal .controls[data-controls-layout="edges"] .navigate-right {
top: 50%;
right: 8px; }
.reveal .controls[data-controls-layout="edges"] .navigate-up {
top: 8px;
left: 50%; }
.reveal .controls[data-controls-layout="edges"] .navigate-down {
bottom: 8px;
left: 50%; } }
</style>
CSS を 持ってきただけでは、コントロール・ボタンは変化しません.
実は(実はが多い…)、コピーしたスタイル controls-arrow
を 適用するためのタグが必要です. これも公式デモと JavaScript が 異なっている点になります.
さすがに reveal.js
本体を変更したくないですし、CDN からとってこれないのも困ります.
なのでイベント・フックを使って HTML が 生成された後に、必要となる要素を追加するようにしました.
以下のコードを HTML の <script>
タグ にある、 Reveal.initialize({});
の 下に追加します.1
2
3
4
5
6
7
8
9
10
11<script>
Reveal.addEventListener('ready', (event) => {
document.querySelector('aside.controls').dataset.controlsBackArrows = 'faded';
Array.from(document.querySelectorAll('aside.controls > button'), e => {
let child = document.createElement('div');
child.setAttribute('class', 'controls-arrow');
e.appendChild(child);
e.style.color = 'rgb(66, 175, 250)';
});
});
</script>
reveal.js で コンテンツの準備ができた ready
イベントで、以下の処理をしています.
querySelector('aside.controls')
で、コントロール・ボタンを保持しているコンテナの要素取得します.
データセット controlsBackArrows
に faded
を 設定し、戻るボタン(左と上) に ボタンが薄くなるようなエフェクトをつけます.
querySelectorAll('aside.controls > button')
で、すべてのコントロール・ボタンを取得します.
各ボタンの子要素に <div class="controls-arrow"></div>
タグをを追加、このタグが先の CSS の 適用先になります.
そして、ボタンのスタイルに rgb(66, 175, 250)
で カラーを設定します. ボタンの青のカラーが、上記 CSS の コピーでは上手く持ってこれないので、スタイル属性で適用しました.
これで、コントロール・ボタンのスタイルが公式デモのように [ > ] に なりました!
が、よくよくスライドを進めていくと、下スライドがある時に配置がずれてる…
どうも、元の [ ▶ ] の時に配置された CSS が 残っているようで、コピーしただけでは上書きできなかったようです.
再度 HTML に <style>
を 追加して大きさと配置を修正します.1
2
3
4
5
6
7<style>
.reveal .controls .controls-arrow:before, .reveal .controls .controls-arrow:after { width: 1.4em; }
.reveal .controls .navigate-left, .reveal:not(.has-vertical-slides) .controls .navigate-left { top: 60px; left: 40px; }
.reveal .controls .navigate-right, .reveal:not(.has-vertical-slides) .controls .navigate-right { top: 60px; left: 60px; }
.reveal .controls .navigate-up, .reveal:not(.has-vertical-slides) .controls .navigate-up { top: 50px; left: 50px; }
.reveal .controls .navigate-down, .reveal:not(.has-vertical-slides) .controls .navigate-down { top: 70px; left: 50px; }
</style>
.controls-arrow:after { width: 1.4em; }
が ボタンの大きさになります.
その下の4つが、配置です. 大きさに合わせて配置を揃えていきます.
コンパクトになり、配置もそろいました!
最初のスライドはよいとしても、メインのコンテンツ以外で動くものがあるのは、如何なものかとは思います. とはいえ縦方向にもスライドができるというは、あまりないのかなと思うと、ナビゲーションのために少し動いてもいいのかなと思い、公式デモから持ってきました.
まずは、少し動くアニメーションのスタイルです. 下矢印が動いて、戻るときに右矢印が動きます.
各%の数値を同じにすると、同時に動きます.1
2
3
4
5
6
7
8
9
10<style>
@keyframes bounce-right {
0%, 35%, 50%, 65%, 75% { transform: translateX(0); }
45% { transform: translateX(2px); }
55% { transform: translateX(-1px); } }
@keyframes bounce-down {
0%, 10%, 25%, 40%, 50% { transform: translateY(2px); }
20% { transform: translateY(2px); }
30% { transform: translateY(2px); } }
</style>
続いて、最初のスライド と 下があるスライド の 際にアニメーションさせる JavaScript を 作ります.Reveal.addEventListener('ready', (event) => {})
は 上記ボタンの子要素を追加したときに記述した部分へ if(){}
を 追記します.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<script>
Reveal.addEventListener('ready', (event) => {
if (Reveal.availableRoutes().right) { document.querySelector('.navigate-right').classList.add('highlight'); }
if (Reveal.availableRoutes().down) { document.querySelector('.navigate-down').classList.add('highlight'); }
});
Reveal.addEventListener('slidechanged', (event) => {
Array.from(document.querySelectorAll('aside.controls > button.highlight'), e => { e.classList.remove('highlight') });
if (event.indexh === 0 && event.indexv ===0) {
document.querySelector('.navigate-right').classList.add('highlight');
}
if (Reveal.availableRoutes().down) {
document.querySelector('.navigate-down').classList.add('highlight');
if (Reveal.availableRoutes().right) {
document.querySelector('.navigate-right').classList.add('highlight');
}
}
});
</script>
Reveal.addEventListener('ready', (event) => {});
で reveal.js の 描画が終わった後に、右矢印 と 下矢印 の それぞれが有効な場合に highlight
の CSS クラスを適用します. Reveal.availableRoutes()
で 指定する方向のスライドがあるかを判定できます.
Reveal.addEventListener('slidechanged', (event) => {});
では、スライドが変更された際のイベントで処理ができます.
まずは highlight
を すべて解除します.
続いて indexh
と indexv
が 0
、つまり最初のスライドの場合に、右矢印に highlight
を 設定.
そして、下方向がある場合に下矢印に highlight
し、さらに右方向がある場合は右矢印にも highlight
を 設定します.
これで、完成になります.
キャプチャは、動きが小さすぎて変化が分かるのが取れませんでした.
日本マイクロソフト株式会社 の 澤さん の プレゼンに関する書籍です. マイクロソフトテクノロジーセンター の センター長 を 勤め、マイクロソフト社のエバンジェリストを率いられています.
こちらの書籍は、プレゼンのためのテクニックというよりも、なぜプレゼンをするのか、なぜプレゼンが必要なのかという点から書かれています. ここでの「プレゼン」は 大人数を前にしたようなプレゼンではなく、営業だとか、自分の考えを伝えるためだとかにも当てはまり、ビジネス・スキルとしても役立ちます.
プレゼンを作る際にはいつも読み返す、基本の立ち位置として重宝しています.
漫画家の三田紀房さん の 書籍です. ドラゴン桜 や エンゼルバンク などが有名ですが、ビジネス関係の書籍も出されています.
こちらは、その中でもプレゼンに関する書籍で、プレゼンを一つの物語として考えてみようというものになります. 一般的なプレゼンの書籍とは一線を画すので、好みが分かれるところだと思います. ご自身の漫画を例に、どのようにスライドを作るのかについて書かれています.
プレゼンだけではなく、アイデアの練り方などにもふれているのがよく、たまに読み返しては様々なことに思いを巡らせたりしています.
デザイン・センスとか、スキルがないのに、どうしてもスライドのデザインとか気になってしまうんですよね… 絵が描けたりする人がうらやましいです.
今回は公式デモを真似するので、CSS を 上手く当てはめることでできましたが、JS や CSS 本体にデモ用の改変が入っていたので、HTML 側だけで合わせるのが難しかったです. 上手くできてよかった.
プレゼンテーションや発表などで、お話をする際にはプレゼンテーション・スライドを用意するかと思います. 普段 PowerPoint を使って作るケースが多いのですが、最近はコーディングな仕事をしているので、せっかくだから Markdown で スライドづくりをしてみたいと思います.
作業環境
論より何とかではないですが、まずは 公式デモ を ざっくり動かしてみるとよいと思います. プレゼンテーション・スライド風なページが表示されます. キーボードの [→] ボタンを押下ないし、右下のコントロールから [>] を クリックするとスライドして次のページが表示されます.
少し進んでいくと右下のコントロールに「v」が 表示され、下へもスライドできます.
なんと、これらを Markdown で 書くことができ、Web で 公開までもできるのが、reveal.js に なります.
基本的な機能どころか、発表でも十分使える機能があります. 以下に主な機能を抜粋します.
発表時は、[S] キー を 発表者ツールを表示し、スライド側をプロジェクタ等に移動して [F] で フルスクリーン表示します.
まずは、reveal.js を 使う HTML を 作成します. 大枠としては以下のような感じになります.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<meta charset="utf-8">
<title>Presentation</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/css/reveal.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/css/theme/white.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/lib/css/zenburn.min.css" />
<script>
let link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ?
'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/css/print/pdf.min.css' :
'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/css/print/paper.min.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<div class="reveal">
<div class="slides">
<section data-markdown="contents.md"
data-separator="^\n\n---$"
data-separator-vertical="^\n>>>$"
data-notes="^Note:"
data-charset="utf-8">
</section>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/lib/js/head.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/js/reveal.min.js"></script>
<script>
Reveal.initialize({
dependencies: [
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/lib/js/classList.js', condition: function() { return !document.body.classList; }},
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); }},
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/plugin/markdown/markdown.min.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/plugin/notes/notes.min.js', async: true },
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/plugin/zoom-js/zoom.min.js', async: true },
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0/plugin/highlight/highlight.min.js', async: true, callback: function () { hljs.initHighlightingOnLoad(); }}
]
});
</script>
JavaScript や CSS は CDN の cdnjs.com さん から配信いただくようにしました.
テーマは 白ベースの white.min.css
に しました. テーマは公式デモの THEMES で試すことができます.
<div class="slides">
配下の <section>
が Markdown ファイルの読み込みと、書式の定義になります.
data-markdown
は、読み込む Markdown ファイル名です.data-separator
は、スライドの区切りを示す正規表現です. 今回は改行2つの後に ---
で次のスライドになります.data-separator-vertical
は、垂直方向スライドの区切り正規表現です. 今回は改行1つの後に >>>
にしました.data-notes
は、発表者ノートのパートを表す正規表現です. 行頭から Note:
になります.data-charset
は、Markdown ファイルの文字セットです.<section data-markdown="contents.md"... >
で 指定したファイルを作成します.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
28# 最初のページ
---
## 2枚目のページ
- 起: 事実や出来事を述べる
- 承: 『起』で述べたことに関することを述べる
- 転: 『起承』とは関係のない別のことがらを持ち出す
- 結: 全体を関連づけてしめくくる
---
## 3枚目のページ
ここに本文を書いていく
Markdown を 使うことができる
>>>
### 3枚目のページ の 下
下のページ
左右の流れと、上下の流れ が作れる
---
## 4枚目のページ
Note: これは発表者ノート
ここまででスライドづくりは完了ですが、外部ファイル の Markdown で スライド作成をすると、表示するには HTTP サーバー が 必要となります. HTML 内に書いてしまうという手もあるのですが、Markdown は 別にしておきたいので HTTP サーバー を 立てる方向で考えました.
Browsersync は ローカル の HTTP サーバーとして動作し、ファイルの変更を検出したらブラウザをリロードしてくれるツールになります.1
2
3
4
5
6
7
8
9
10
11
12c:\Develop\repos\slack-bot> npm install -g browser-sync
c:\Develop\repos\slack-bot> browser-sync start --server --files **/*
[Browsersync] Access URLs:
-----------------------------------
Local: http://localhost:3000
External: http://192.168.0.100:3000
-----------------------------------
UI: http://localhost:3001
UI External: http://192.168.0.100:3001
-----------------------------------
[Browsersync] Serving files from: ./
[Browsersync] Watching files...
Browsersync が 起動すると、ブラウザで自動的にページが表示されます.
スライド・マップを見ると単純な例ですが、ちゃんと上下のスライドも使えています.
スライド作りとなると、どうしても欲しくなるのが パワポマン こと、パワーポイントの人型のアイコン、本投稿のアイキャッチにも使っているクリップアートさんたち. 以前はクリップアートの検索で、アバター とか Style 1541 などで検索できていましたが、いつの間にかなくなってしまったというのがありました.
それについては、こちら いつか消えた PPT の アバター とか、 Style 1541 とか に まとめましたので、よろしいかったら ご覧ください.
なお、クリップアート自体は マイクロソフト クリップアート 復刻 さん から入手できます.
パワポマンはいつもお世話になっております. 復刻してくださり ありがとうございます!
日本マイクロソフト株式会社 の 澤さん の プレゼンに関する書籍です. マイクロソフトテクノロジーセンター の センター長 を 勤め、マイクロソフト社のエバンジェリストを率いられています.
こちらの書籍は、プレゼンのためのテクニックというよりも、なぜプレゼンをするのか、なぜプレゼンが必要なのかという点から書かれています. ここでの「プレゼン」は 大人数を前にしたようなプレゼンではなく、営業だとか、自分の考えを伝えるためだとかにも当てはまり、ビジネス・スキルとしても役立ちます.
プレゼンを作る際にはいつも読み返す、基本の立ち位置として重宝しています.
漫画家の三田紀房さん の 書籍です. ドラゴン桜 や エンゼルバンク などが有名ですが、ビジネス関係の書籍も出されています.
こちらは、その中でもプレゼンに関する書籍で、プレゼンを一つの物語として考えてみようというものになります. 一般的なプレゼンの書籍とは一線を画すので、好みが分かれるところだと思います. ご自身の漫画を例に、どのようにスライドを作るのかについて書かれています.
プレゼンだけではなく、アイデアの練り方などにもふれているのがよく、たまに読み返しては様々なことに思いを巡らせたりしています.
スライドづくりの環境準備ができました!
Markdown で 書くので、パワポに比べて表現力は落ちるでしょうが、しばらくはキレイで派手なスライドから離れるので、サクサク書ける Markdown のが嬉しいです. まずは、reveal.js で ドンドン書いてみよう♪
しばらく前にブログのソース・ファイルの名前を変更したことがありました. その際に関連するリンクの修正を忘れていたものが多かったらしく、久しぶりに見た Google Search Console で 23件もの 404 Not Found、ページが見つからないというエラーが報告されていました. リンク切れを直すとともに、404 エラー が 発生した場合に表示されるページを GitHub Pages に なっていたものを、ブログ用のページに直しました. 404 ページを設置にあたっては、Hexo で Markdown を 書き、GitHub Pages に 設定します.
作業環境
404 ページ を 設定していない場合は、存在しない URL へ アクセスすると以下のようなページが表示されます.
ウェブサイトを GitHub さん の GitHub Pages で ホストさせていただいているので、何もしなければ GitHub さん の 404 ページになります. 何を表示してよいのかわからないから、当然そうなりますね.
このページが表示されると、来ていただいた方にトップ・ページへさえも、戻ってもらうための手段が提供できないという問題があります.
内部のリンクをたどってきてくださった方は戻ることができますが、直接来た方は URL を 修正して、、、までは見ないですよね. (たぶん)
内部リンク切れは修正するとしても、404 が 表示される可能性は残ります.
その場合に備えて、404 ページ自体も自サイトのものにします.
GitHub Pages で 404 ページを設定するには、サイトのソース・ルートに 404.html
を 置きます.
下記例は Hexo を 使っていない場合に、単純な 404.html
を 置いたものになります. ホームへのリンクなどを設置していない簡単なものですが、独自のページになっていることが分かります.
Hexo を 使って ウェブサイトを作っている場合は、Hexo の Markdown で 404 ページを作ります.
ソースルート直下の source
ディレクトリに 404.md
を 作ります.1
2
3
4
5
6
7---
layout: page
title: Page not found
comments: false
---
ページが見つかりませんでした.
アクセスすると以下のようなページが表示されます.
タイトールと、コンテンツがちゃんと表示されているのが分かります. そして カバーの画像 や カテゴリー など、サイトの構成もそのままなので、トップへ戻ったり、カテゴリーやタグを選びなおすなどの選択ができるようになります.
なお、 404.html
を 直接置いた場合ですが、これは Hexo に 取り込まれコンテンツ部分に埋め込まれるので、完全に別ページを作るということはできなそうです.
サイトの構成にうまく入り込んでくれたおかげで、すべてを作りこむ必要がなくなったのが助かります. 一方で 日付 や Share の リンク、関連記事 などが表示され、記事の1つのような感じが出ています. (※ 関連記事は、こちら Hexo に 関連する記事のリストを追加する で 追加した Plugin に なります)
これを非表示にするにはテンプレートを修正する必要があります.
今回はデフォルト・テンプレート Landscape をつかっているので、Landscape を カスタマイズしました.
修正するファイルは /themes/landscape/layout/_partial/article.ejs
です.
以下の3ヵ所を <% if (post.path != "404.html"){ %>
- <% } %>
で 囲みます.
<div class="article-meta">
ブロック<footer class="article-footer">
ブロック<nav id="related-posts"...>
ブロック以下、 article.ejs
修正箇所 の 抜粋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
28
29
30
31
32<article id="<%= post.layout %>-<%= post.slug %>" class="article article-type-<%= post.layout %>" itemscope itemprop="blogPost">
<% if (post.path != "404.html"){ %>
<div class="article-meta">
<%- partial('post/date', {class_name: 'article-date', date_format: null}) %>
<%- partial('post/category') %>
</div>
<% } %>
<div class="article-inner">
...(省略)
<% if (post.path != "404.html"){ %>
<footer class="article-footer">
<a data-url="<%- post.permalink %>" data-id="<%= post._id %>" class="article-share-link"><%= __('share') %></a>
<% if (post.comments && config.disqus_shortname){ %>
<a href="<%- post.permalink %>#disqus_thread" class="article-comment-link"><%= __('comment') %></a>
<% } %>
<%- partial('post/tag') %>
</footer>
<% } %>
...(省略)
</article>
<% if (post.path != "404.html"){ %>
<nav id="related-posts" class="article-inner" style="font-size: smaller">
<div class="article-entry">
<h2>関連記事</h2>
<%-
popular_posts({ PPMixingRate: 0.0 })
%>
</div>
</nav>
<% } %>
...(省略)
テンプレートを適用し、若干文章を直して、こんな感じになりました.
無事、404 エラー に対して コンテンツを返せるようになりました.
内部リンク切れで 404 は 出してはいけないものなので反省しつつ、何かの拍子で出てしまってもサイト内へとどまっていただけるようにできたかと思います.
いつかは、こちら デザインの参考にしたい!404(not found)ページ33選 で 紹介されるような、ステキな 404 ページを作ってみたいものです.
OSMC として使っている Raspberry Pi Zero が よくフリーズするようになり、ケースをさわってみると暖かいことから熱対策をすることにしました. そのための ヒートシンク付きケースを C4 Labs さん から購入 しました.
そのままヒートシンクを付けたいところ、ちょっと待って簡易的ではありますが Raspberry Pi の 温度を取得して変化を見てみたいと思います.
作業環境
Raspberry Pi の 温度は /sys/class/thermal
あたりに格納されています.
そこからファイルを参照することで取得できます. 温度は 1,000倍 になっています.1
2pi@raspberrypi:~ $ cat /sys/class/thermal/thermal_zone0/temp
34166
上記の場合は 34.166 ℃ ということになります.
切り捨てにはなりますが expr
コマンドと組み合わせると、こんな感じにもできます.1
2pi@raspberrypi:~ $ expr `cat /sys/class/thermal/thermal_zone0/temp` / 1000
34
上記は OSMC で 使っている Raspberry Pi Zero で、Crystal Signal Pi の Raspberry Pi 3 は 57996 でした.
また vcgencmd
というコマンドを使っても温度を取得することができます.
こちらは記号も入っています. (2バイト文字がないから ‘C で ℃ を 表現するんですね)1
2 vcgencmd measure_temp
temp=34.2'C
ローカルファイルに取得した温度を追記していき、どのように変化しているのかが分かるようにします.
ヒートシンクの有無で温度の変化が出るかを見たいだけなので、単純に cron
で 上記コマンドを仕掛けておくようにします.
OSMC は cron
が 入っていなかったので、インストールします.1
2pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install cron -y --no-install-recommends
10分に1回なので */10 * * * *
で 指定し、日付 と 温度 を /tmp/thermal.txt
に 追記します.
※ /tmp
は リブートするとファイルが消えるので恒久的に取っておく場合は他のディレクトリにします.1
2pi@raspberrypi:~ $ crontab -e
*/10 * * * * /bin/echo -e "`date`\\t`cat /sys/class/thermal/thermal_zone0/temp`" >> /tmp/thermal.txt
こんな感じで出力されます. 特に処理していない状態で 10分間なので温度変化は無いようです.1
2
3pi@raspberrypi:~ $ cat /tmp/thermal.txt
Thu Sep 28 15:30:01 JST 2017 37932
Thu Sep 28 15:40:01 JST 2017 37932
Raspberry Pi に 光り輝く四角柱 を 立てた Crystal Signal Pi、ついに Amazon.co.jp さん で 買えるようになりました! 実物を見ると輝く姿に圧倒されます. 監視用とのことですが、天気に合わせて色を変えたりと楽しめます.
ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロ や Raspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
10分間隔で取得するようにしたので、これで温度の変化を知ることができます. しばらく記録しておき、ヒートシンクを付けてから違いを確認したいと思います.
本来はちゃんとした監視ツールなどでデータ収集してグラフ化などしたいところですが、直近の問題と対策を検討するようなのでスクリプトで逃げました. ラズパイの台数が多いので、ちゃんと監視できるようにしたいところです. ラズパイの監視は何のツールがいいんだろう…
最近 OSMC として使っている Raspberry Pi Zero が よくフリーズするようになってしまいました. この夏の暑さが原因かなと思われるので、ヒートシンク付きケースを購入し、様子見をすることにします. この辺の調査などは別途.
Raspberry Pi Zero の 大きさだと、ヒートシンクの効果が小さいとの話も聞きますが、他にも面白そうなプロダクトを作っているメーカーさんを見つけたので、思い切って購入しました. 購入方法は難しくは無いのですが、また買いたくなった時の記録として.
今回購入したのは C4 Labs という メーカーさんで、アメリカのシアトル近郊にある会社のようです.
カタログ https://c4labs.net/collections/all を ざっと眺めていくと、Raspberry Pi や Arduino 関連だけではなく、サイコロ用のトレイや、ダイスタワー、RPG Game Box といったボードゲーム用のアクセサリーも作っているようです. デザインがカッコよく、どれこれも欲しい!
欲しいものの悩みは尽きないものですが、今回の目的の品であるヒートシンク付きケースはこちら Zebra Zero Heatsink Black Ice Case for Raspberry Pi Zero 1.3 and Zero Wireless.
Pimoroni さん の Pibow Zero Case を 黒のシックな感じにしてヒートシンクが付く感じになります.
合わせて購入したのが Raspberry Pi Zero に ブレッドボードをセットにできるケース Zebra Zero Plus Breadboard in Wood for Raspberry Pi Zero 1.3 & Zero Wireless.
今回は内部が木製のデザインを選びましたが、上記ヒートシンク付きケースのようなデザインの Black Ice モデル も あります.
ブレッドボードを使うときに一緒のケースになっていると便利かなということで買ってみました.
実際に作ってみてから気になったのですが、Raspberry Pi を ケース内に入れてネジ止めしてしまうので、簡単に取り外せないので専用となってしまいます. Zero や Zero W なので 専用にしてしまってもよいかな…
Explorer HAT Pro とかの方が色々できるのかもしれませんが、ちゃんと使いこなせるレベルではないので、まずはブレッドボードをちゃんと扱えるようになってから手を出したいと思います.
なんかカッコよかったので手を出してしまいました (;´・ω・)
まだ使うあてを考えてないのですが、せっかくなので Raspberry Pi + Camera で 遊んでみようと思い買ってみました.
Cookie Wheel Camera Case for the Raspberry Pi Camera v1 and v2 (not included)
購入する製品のページにある [ADD TO CART] の ボタンをクリックして、カートに追加します.
画面が左にスライドして、カードの状況を見ながらショッピングができます.
購入する製品を追加し終わったら、カートから [CHECK OUT] ボタンをクリックします.
チェックアウト画面が標示されるので、必要な情報を入力していきます.
入力できたら [Continue to shipping method] ボタンをクリックします.
※ 配送先の住所は画像サンプル用に東京駅を借りてます.
配送方法は [Invasion International Shipping] になります.
[Continue to payment] ボタンをクリックします.
$24.0、ちょっと高いっす. [FREE SHIPPING to ANYWAY in the USA!] なのに…
支払方法を選択します.
クレジットカードは海外のサイトなのに JCB にも対応しています. また PayPal、bitcoin なども使えます.
Amazon Pay は Amazon.com に つながりますが、Amazon.co.jp の アカウントも引っ張れたので使えるような感じでした. 今回は PayPal を 使ったので最後までコミットしなかったので、何とも言えませんが.
支払方法を確定したら [Complete order] ボタンをクリックして注文を確定します.
※ PayPal の 利用法については Raspberry Pi Zero の 購入 の 手順と同じでした
注文が確定され、送付先情報で入力したメールアドレスにメールが届きます. これで無事に注文が完了し、後は届くのを待つのみです. Google Maps で 届け先が表示されます. (※ サンプル用で東京駅を指してます)
約1週間ぐらいで届きました!
ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロ や Raspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
Raspberry Pi Zero の ヒートシンク付きケースとなると、なかなか無く、今回素敵なケースを購入することができてよかったです. 合わせて面白そうなプロダクトも手に入りました.
配送料がネックにはなりますが、日本にも届けてくれるサイトも増えてきたようで助かります.
GitHub 社から、公式のデスクトップ・クライアントのアプリ GitHub Desktop がリリースされました! Atom エディターなどで使われている Electron で 作られています. Electron アプリは開発側のメリットが大きく言われていますが、快適な操作性と、素敵なデザインのアプリが多く、Electron の 開発元でもある GitHub 社のアプリとなると楽しみます. さっそく使ってみます.
作業環境
GitHub 社 が リリースした、公式の GitHub クライアント・アプリです. これまでβリリースされていましたが、 2017年9月19日に正式にバージョン 1.0.0 が リリースとなりました.
ベータ版では、残念なことに私の環境では動作しなかった(正確にはクローンとかができなかった) ので、正式リリースとのことで楽しみです.
GitHub Desktop が サポートしているかは試してみるとして、GitHub の クライアント・アプリといったときに、こんな機能が欲しいという期待があります. まぁ、特殊な使い方をしている部分もあるので、あったらラッキーぐらいでしょうし、なければ自分で作るべきなのでしょうが腕が追い付かず…
ともあれ、これから使わせていただく GitHub Desktop、こんなことできるかな?
Pull Request レビュー & マージ を 専用アプリで
最近はレビューする機会が増え、Pull Request を 見ることが多くなりました.
そうなると、Pull Request の 通知から始まり、やり取りの管理などが簡単に行るようになると助かります. ブラウザでも十分なエクスペリエンスを提供していただいていると思いますが、ブラウザで特定のページを固定的に扱うのが得意でなく、できれば専用アプリで使いたいというのがあります.
複数アカウントをワンストップで
そもそも複アカするな、という話もあると思います orz なぜこんなことになっているのか、自分でも困り果てているのですが 使わないといけない GitHub アカウントが多いのです…
ブラウザだと Sign in して 2FA して、Sign out して次. かなり厳しいです. この辺が便利になってくれると嬉しいです.
そんな、超個人的な期待はよそに、インストールを進めます.
GitHub Desktop の ウェブサイト https://desktop.github.com/ へ アクセスします.
環境に合わせてボタンが用意されているのでダウンロードします. 今回は [Download for Windows (64bit)] を 選択しました.
ダウンロードされた [GitHubDesktopSetup.exe] を ダブルクリックします. チェックサムは見つかりませんでした. 確認したいなぁ…
インストール先やオプションを聞かれることなく、インストールが実行されます. しばし待ちます.
Welcome が 表示されます. 今回は [GitHub.com] へ サインアップしました. GitHub Enterprise にも対応しているようです.
GitHub の Username(or Email) と Password を 入力して [Sign in] を クリックします. 2FA を 有効にしている場合でもパスワードで大丈夫です. 次でコードを聞かれます.
2FA を 有効にしているので、コードを聞かれました. コードを入力して [Verify] します. (2FA を 有効にしていない場合は表示されません)
続いて Git の Name と Email を 聞かれます. GitHub で 設定した Username と Email を 入力します. 合っていないと下記画像のように自分の相子ではなく Hubot アイコンが表示されるようです. (Web の GitHub 上でもアイコンが異なり困るので、ちゃんと合わせるようにします)
最後に改善のための匿名レポートを送るかを選択し、[Finish] ボタンをクリックします.
インストールは、ここまでとなります.
引き続きメイン画面が標示されるので、作業を進めます.
無事、GitHub Desktop の 画面が標示されました.
まだリポジトリが追加されていないので、追加します. 今回は初回ということで一番右のクローンから始めました.
すでにログインしているので、自分のアカウントに関連するリポジトリが表示されます. クローンするリポジトリを選択し [Clone] ボタンをクリックします. 今回は、このブログのソースを選択しました.
しばらく待つとクローンされ、画面左上に現在選択しているリポジトリが表示されます. なお、新規クローンなのでローカルに変更はないのでリポジトリ名以外、操作を必要とするような変化はありません.
リポジトリの編集をします. これは GitHub Desktop の スコープではなく、メニュー の [Repository] から [Open in XXXX] を 選択します. 今回の環境は Visual Studio Code が 該当するため Visual Studio Code に なっています. Atom が 入っている場合は Atom が 表示されるでしょう. (設定変更は後述)
ソース編集した Visual Studio Code は、こちらの記事のスコープ外なので編集できたとして、GitHub Desktop に 戻ると Git の 更新が表示されます. (表示されない場合は右上の [Fetch origin] を クリックします)
ここでは、本記事の前の Raspberry Pi 基盤 の LED を 消灯する の 変更がリストされています.
左下のフォームで、コミットのサマリと説明を入力し、[Commit to source] ボタンをクリックするとコミットできます.
※ このリポジトリのデフォルト・ブランチが source
なので [Commit to source] ですが、変更していない場合は [Commit to master] です.
コミットされると何もないような画面に戻りますが、画面右上の [Fetch origin] が [Push origin] に なっています. ここをクリックすることで GitHub へ Push できます.
今回は Visual Studio Code しか入っていない環境だったため、エディタの選択が Visual Studio Code でしたが Atom も 入っている場合や、Shell 設定を変更したい場合があります.
メニューの [File] から [Options…] を クリックします.
Options ダイアログ の [Advanced] タブ から、変更できます.
GitHub への Sign in アカウントの変更や、Git の Name/Email の 変更もこちからできます. 左下に Hubot アイコンが出ている場合は、こちらから Git の 設定を直します.
以上。
なんか、クローンしてプッシュして終わりな感じですが、v1.0.0 では ここまでのようです. ブランチを作ったり切り替えたりできますが、Issues や Pull Request などは これからのようです.
まずは基本機能から. これからを楽しみにしたいと思います!
]]>Raspberry Pi の 基盤には ACT と PWR の LED があります. 普段から Crystal Signal Pi の 四角柱を光らせていますが、壁際においているため PWR の 赤 LED が 反射し色が混ざるのと、夜間消灯中にも壁に反射する赤色が気になるので、基盤 の LED を 消灯したいと思います.
作業環境
まずは、現在の状況.
日中 の Crystal Signal Pi 点灯中でも、白い壁に反射する 赤 LED が ちょっと気になります…
夜間消灯中に輝く PWR の 赤 LED. 白い壁に反射して赤に染まっています. これだけの光量だと離れていても、棚の一角が かなり赤く光ります.
Raspberry Pi というか Raspbian Jessie で 基盤 の LED を 操作するには、 /sys/class/leds/
にある led0
と led1
ディレクトリのファイルを操作します. led0
が ACT で led1
が PWR です.
操作するファイルは 2つで、 trigger
と brightness
です. trigger
は LED を 光らせるトリガーで、 brightness
は LED の 明るさです.
まず、現在の設定を確認します.led0
ACT は mmc0
で 255
. つまり SD カード の 読み書きをトリガーとして最大光量で点灯します.led0
PWR は input
で 255
. つまり電源の有無をトリガーとして最大光量で点灯します.
1 | pi@raspberrypi:~ $ cat /sys/class/leds/led0/trigger |
では、これらに設定をして消灯します.trigger
を none
にすることで、LED を 点灯するアクションを起こさせなくします. 続いて、brightness
を 0
にして消灯します.led0
ACT は 点滅なので trigger
を 止めれば消えている状態になるはずですが、SD カードへアクセス中の瞬間にあたると点灯したままになるので、その場合は brightness
を 0
にして消灯します. (イベントからのトリガーが止まるだけで、明るさとは関係ないということですね)
1 | pi@raspberrypi:~ $ echo none | sudo tee /sys/class/leds/led0/trigger |
こちらは現在の状態を変更するものなので、設定したとおりに LED が すぐに消灯します. これで光が混ざらなくなって気にならないし、夜間消灯も完全に消えてくれます.
なお brightness
の 数値で明るさの変化は見られませんでした. 0
1
で ON/OFF ぐらいのもののようです. 初期値 と max_brightness
の 値が 255
なので変化できそうなのに…
上記設定方法は現在の設定変更で使えるものになります. そのためリブートすると元の状態に戻ります.
恒久的に設定するには /boot/config.txt
に 設定を記述します.
設定の詳細については /boot/overlays/README
ファイル、もしくは最新になりますが raspberrypi/firmware の firmware/boot/overlays/README を ご確認ください.
1 | pi@raspberrypi:~ $ echo "dtparam=act_led_trigger=none,act_led_activelow=on" | sudo tee -a /boot/config.txt |
Raspberry Pi Zero は PWR LED しかないので、コマンドラインからは led0
で 設定します./boot/config.txt
は act_led_~
なので変わらずです.
Raspberry Pi に 光り輝く四角柱 を 立てた Crystal Signal Pi、ついに Amazon.co.jp さん で 買えるようになりました! 実物を見ると輝く姿に圧倒されます. 監視用とのことですが、天気に合わせて色を変えたりと楽しめます.
ラズパイを始めるには 全部入りの Raspberry Pi 3 が 手ごろではないでしょうか. Raspberry Pi Zero - ラズベリー・パイ ゼロ や Raspberry Pi Zero W - ラズベリー・パイ ゼロ W は 国内では入手しずらいため値上がりしてしてますし、GPIO ピン も 自分で付ける必要があったりと色々と手がかかります. その分楽しいというのもありますが.
届くまで時間がかかってもよい場合は こちら Raspberry Pi Zero の 購入 で 記事にしました Pimoroni さん から購入する手もあります.
Raspberry Pi 3 は 5V/3A の 電源が必要になります. スマホの充電アダプタでは出力が足りない場合もあるので確認が必要です.
ラズパイ の OS や ストレージに必要です. 16GB あれば十分だと思いますが、用途次第なので お好みのサイズで用意します.
Raspberry Pi の 基盤には PWR の 赤 LED のほかに、ACT の 緑 もありますが、緑は点灯では無く点滅であり、強く光り続けないので今回は PWR の 赤だけを消灯することにして様子見しようと思ったら、やはり気になるので一緒に消しました. 意外と光るものなんですね. (;^_^A
]]>TSLint について調べた ので、実際の設定を考えます.
作業環境
TypeScript は 学習中のため、設定の良し悪しが分からないところがありますが、まずは厳しくシメテおくのが良いと考えます.
この手のチェックは、後から緩めることは簡単ですが、後から厳しくすると指摘の嵐に見舞われ結局使わないといったことにもなりかねません. まずは厳しく、どうしても指摘事項に対する代替策が無かった場合に緩めるといった運用にします.
以下の 2つは設定しませんでした. 今のところ禁止するものが 無い and/or 想像がつかない ので、設定するべき値がないためのとなります. (デプリケートではないもので、禁止した方が良いものってあるのかなぁ)
以下にような設定 tslint.json
を 作りました. (行数削減のため一部整形済み)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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151{
"rules": {
"adjacent-overload-signatures": true,
"member-access": true,
"member-ordering": [ true, { "order": [ "static-field", "instance-field", "constructor" ]}],
"no-any": true,
"no-empty-interface": true,
"no-import-side-effect": true,
"no-inferrable-types": true,
"no-internal-module": true,
"no-magic-numbers": true,
"no-namespace": true,
"no-non-null-assertion": true,
"no-reference": true,
"no-unnecessary-type-assertion": true,
"no-var-requires": true,
"only-arrow-functions": [ true ],
"prefer-for-of": true,
"promise-function-async": true,
"typedef": [
true,
"call-signature",
"arrow-call-signature",
"parameter",
"arrow-parameter",
"property-declaration",
"variable-declaration",
"member-variable-declaration",
"object-destructuring",
"array-destructuring"
],
"typedef-whitespace": [
true,
{ "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" },
{ "call-signature": "onespace", "index-signature": "onespace", "parameter": "onespace", "property-declaration": "onespace", "variable-declaration": "onespace" }
],
"unified-signatures": true,
"await-promise": true,
"curly": [ true, "ignore-same-line" ],
"forin": true,
"import-blacklist": true,
"label-position": true,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-console": [ "debug", "error", "info", "trace", "warn" ],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-duplicate-variable": [ true, "check-parameters" ],
"no-empty": true,
"no-eval": true,
"no-floating-promises": true,
"no-for-in-array": true,
"no-inferred-empty-object-type": true,
"no-invalid-template-strings": true,
"no-invalid-this": [ true, "check-function-in-method" ],
"no-misused-new": true,
"no-null-keyword": true,
"no-object-literal-type-assertion": true,
"no-shadowed-variable": true,
"no-sparse-arrays": true,
"no-string-literal": true,
"no-string-throw": true,
"no-submodule-imports": true,
"no-switch-case-fall-through": true,
"no-this-assignment": true,
"no-unbound-method": true,
"no-unsafe-any": true,
"no-unsafe-finally": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"no-void-expression": [ true, "ignore-arrow-function-shorthand" ],
"prefer-conditional-expression": [ true, "check-else-if" ],
"prefer-object-spread": true,
"radix": true,
"restrict-plus-operands": true,
"strict-boolean-expressions": true,
"strict-type-predicates": true,
"switch-default": true,
"triple-equals": true,
"typeof-compare": true,
"use-default-type-parameter": true,
"use-isnan": true,
"cyclomatic-complexity": [ true, 6 ],
"deprecation": true,
"eofline": true,
"indent": [ true, "spaces", 4 ],
"linebreak-style": [ true, "LF" ],
"max-classes-per-file": [ true, 1 ],
"max-file-line-count": [ true, 300 ],
"max-line-length": [ true, 120 ],
"no-default-export": true,
"no-duplicate-imports": true,
"no-mergeable-namespace": true,
"no-require-imports": true,
"object-literal-sort-keys": true,
"prefer-const": true,
"trailing-comma": [ true, { "multiline": "never", "singleline": "never" }],
"align": [ true, "parameters", "arguments", "statements", "members", "elements" ],
"array-type": [ true, "array" ],
"arrow-parens": [ true, "ban-single-arg-parens" ],
"arrow-return-shorthand": [ true, "multiline" ],
"binary-expression-operand-order": true,
"callable-types": true,
"class-name": true,
"comment-format": [ true, "check-space", "check-uppercase" ],
"completed-docs": [ true ],
"encoding": true,
"file-header": [ true, "Copyright \\d{4}" ],
"import-spacing": true,
"interface-name": [ true, "never-prefix" ],
"interface-over-type-literal": true,
"jsdoc-format": true,
"match-default-export-name": true,
"newline-before-return": true,
"new-parens": true,
"no-angle-bracket-type-assertion": true,
"no-boolean-literal-compare": true,
"no-consecutive-blank-lines": [ true, 2 ],
"no-irregular-whitespace": true,
"no-parameter-properties": true,
"no-reference-import": true,
"no-trailing-whitespace": true,
"no-unnecessary-callback-wrapper": true,
"no-unnecessary-initializer": true,
"no-unnecessary-qualifier": true,
"number-literal-format": true,
"object-literal-key-quotes": [ true, "always" ],
"object-literal-shorthand": true,
"one-line": [ true, "check-catch", "check-finally", "check-else", "check-open-brace", "check-whitespace" ],
"one-variable-per-declaration": [ true, "ignore-for-loop" ],
"ordered-imports": true,
"prefer-function-over-method": true,
"prefer-method-signature": true,
"prefer-switch": true,
"prefer-template": [ true, "allow-single-concat" ],
"quotemark": [ true, "single", "avoid-template", "avoid-escape" ],
"return-undefined": true,
"semicolon": [ true, "always" ],
"space-before-function-paren": [ true, "never" ],
"space-within-parens": 0,
"switch-final-break": [ true, "always" ],
"type-literal-delimiter": true,
"variable-name": [ true, "check-format", "ban-keywords" ],
"whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type", "check-typecast", "check-preblock" ]
},
"defaultSeverity": "error"
}
Visual Studio Code で Hello TypeScript! で作ったコードに TSLint を かけてみます.
作成したコードは以下になります. すでに引っかかることが目に見えていますが、ただの実験コードなので気にせずかけます.1
2
3
4
5
6
7
8class Startup {
public static main(): number {
console.log('Hello TypeScript!');
return 0;
}
}
Startup.main();
コマンドラインで実行するには、 tslint -p
で tsconfig.json
を 指定します.
今回は compilerOptions
に strictNullChecks: true
が 無いので警告されています. また案の定 JSDoc などのドキュメンテーションが引っかかりました.Missing blank line before return
も 出ているので、コードのチェックもしてくれていることが分かります.
1 | PS C:\Develop\workspace\hello-typescript> tslint -p .\tslint.json |
Visual Studio Code では、以下のようにチェック結果がエディタに範囲されています.Documentation
の チェックが反映されていないようですね…
一通りチェックするような設定ができました!
これで、良いプラクティスを反映した文法でコーディングできるので、作るべきことに集中できますし、レビューの際もロジックなどに見るべき場所に注力できますね.
Visual Studio Code で チェックできてないものがありそうなのは、参照しているスキーマが、公式サイトのサンプルと若干ずれているようで、 tslint.json
にも警告が出ていました.
後ほど詳しく調べるとして、とりあえず CI と 組み合わせて、コマンドライン実行の Lint も かけることで、ダブルチェックで逃げることにします.
あとは感覚的にしっくりくる設定なのかガッツりコーディングしてブラッシュアップ、いざっコーディング!
]]>TypeScript の tsconfig.json が とりあえずできました. 次は静的解析ツールの TSLint を 設定する tslint.json の 設定内容について検討します.
作業環境
TSLint は プログラムを動作させずに解析し問題になりそうなコードや規約違反などをチェックする TypeScript 向けの静的解析ツールです. JavaScript では ESLint、Java では SpotBugs(FindBugs) & Checkstyle などが同種のツールにあたります.
TSLint core rules を 確認し、ざっと理解のためのメモを作りました.
英語ができないのと、TypeScript/TSLint に 詳しくない状態で書いているので、間違えや勘違いがあるかもしれないでご注意ください…
英文のままになっているところは、よくわからなかった and/or 日本語で表現できなかった ので、とりあえず そのまま転記しました. いつの日かアップデートできるように頑張りたい.
ルール | 概要 |
---|---|
adjacent-overload-signatures | 関数のオーバーロードは連続して記述し、可読性を向上させる |
ban-types | 特定の型を使用禁止にする |
member-access | クラス・メンバーの可視性宣言を強制させる |
member-ordering | クラス・メンバーの順序付けを強制し、可読性を向上させる |
no-any | any の 型宣言を使用禁止にする |
no-empty-interface | 空のインターフェースを禁止する |
no-import-side-effect | 副作用を伴う import を 禁止する |
no-inferrable-types | number string boolean の 初期化済みの型宣言を禁止し冗長なコードを排除させる |
no-internal-module | 内部 module を 禁止し、新しい namespace キーワードの利用を使用させる |
no-magic-numbers | マジックナンバーを禁止する (ただしデフォルトでは -1 0 1 は 許可) |
no-namespace | 内部 module とnamespace を 禁止し、 ES6-style の import/export を使用させる |
no-non-null-assertion | non-null アサーションを禁止し、strict null checking mode を 活用させる |
no-reference | /// <reference path=> を 禁止し、ES6-style の import/export を使用させる |
no-unnecessary-type-assertion | 型アサーションが、式の型を変更しない場合に警告する |
no-var-requires | import 以外の require を 禁止し、ES6-style の import/export を使用させる |
only-arrow-functions | Arrow-style 以外の function 関数式を禁止し、予期しない this アクセスを防止する |
prefer-for-of | 配列のインデックスにアクセスしないループの場合は、 for-of を 使用させる |
promise-function-async | Promise を 返す関数またはメソッドは async の マークを必須とする |
typedef | 型定義を必須とする |
typedef-whitespace | 型指定子(コロン) の 前後のスペース有無をチェックします |
unified-signatures | union または optional/rest で1つに統合できるオーバーロードを警告する |
ルール | 概要 |
---|---|
await-promise | Promise ではない awaited な 値を警告する |
ban | 特定の関数やグローバル・メソッドを禁止する |
curly | if/for/do/while で 中括弧を必須とする |
forin | for-in の if フィルターを必須とし、継承プロパティへの偶発アクセスを防止する |
import-blacklist | 直接 import require せず、サブモジュール・ロードにして不要なロードを避ける |
label-position | ラベルの使用を do/for/while/switch に限定し、コードの構造化を強化する |
no-arg | arguments.callee を 禁止し、パフォーマンスの最適化を行えるようにする |
no-bitwise | ビット演算子を禁止し、保守性を向上させる |
no-conditional-assignment | do-while/for/if/while での条件文における代入を禁止する |
no-console | 指定するコンソール・メソッド (e.g. log error ) の 仕様を禁止する |
no-construct | String Number Boolean の コンストラクタ利用を禁止し、関数を利用させる |
no-debugger | debugger ステートメントを禁止する |
no-duplicate-super | コンストラクタでの super() 二重呼び出しを警告する |
no-duplicate-variable | 同一スコープでの var 重複宣言を禁止する |
no-empty | 空ブロックを禁止する |
no-eval | eval を 禁止し、危険なコードを防止させる |
no-floating-promises | 関数から返された Promise の ハンドルを厳格にさせる |
no-for-in-array | 配列の for-in ループを禁止し for-of を 利用させる |
no-inferred-empty-object-type | 関数とコンストラクタの呼出し側で、 {} (空オブジェクト型)による型推論を禁止する |
no-invalid-template-strings | テンプレート文字列以外 の ${ を 警告する |
no-invalid-this | クラス外での this キーワードの使用を禁止する |
no-misused-new | Warns on apparent attempts to define constructors for interfaces or new for classes. |
no-null-keyword | null の 使用を禁止し、 undefined に 統一させる |
no-object-literal-type-assertion | インターフェースや |
no-shadowed-variable | 変数のシャドーイングを禁止する |
no-sparse-arrays | 配列リテラルの欠落要素(重複カンマ)を禁止しする |
no-string-literal | 不要な文字列リテラルのプロパティアクセスを禁止し obj.property 書式を使用させる |
no-string-throw | プレーン・テキストの throw を 禁止し、 Error の スローを使用させる |
no-submodule-imports | サブモジュールのインポートを禁止し、最上位パッケージのエクスポートを使用させる |
no-switch-case-fall-through | switch の ケース・フォールスルーをきん資する |
no-this-assignment | 不要な this 参照を禁止し、Arrow-style ラムダを使用させる |
no-unbound-method | メソッドがメソッド呼び出しの外で使用されることを警告する |
no-unsafe-any | 動的な方法の any 型 利用を警告する |
no-unsafe-finally | finally ブロックでの return continue break throws の 使用を禁止する |
no-unused-expression | 未使用の式ステートメントを禁止する |
no-unused-variable | 未使用 の インポート、変数、関数、プライベート・クラスのメンバー を 禁止する |
no-use-before-declare | 変数の宣言前利用を禁止する |
no-var-keyword | var を 禁止し、 let と const を 使用させる |
no-void-expression | Requires expressions of type void to appear in statement position. |
prefer-conditional-expression | Recommends to use a conditional expression instead of assigning to the same thing in each branch of an if statement. |
prefer-object-spread | Enforces the use of the ES2015 object spread operator over Object.assign() where appropriate. |
radix | parseInt を 使う場合に、 radix パラメータの指定を必須とする |
restrict-plus-operands | 変数の加算は双方の型が同じ(number + string は禁止) であることを強制する |
strict-boolean-expressions | ブール式で許可する型を制限する (デフォルトは boolean のみ) |
strict-type-predicates | 常に true もしくは false となる型述語を警告する |
switch-default | switch 文は、 default ケース の 実装を必須とする |
triple-equals | == と != を 禁止し、 === と !== を 使用させる |
typeof-compare | Makes sure result of typeof is compared to correct string values. |
use-default-type-parameter | 明示的に指定された型引数が、その型パラメータのデフォルトである場合に警告する |
use-isnan | NaN 定数の比較を禁止し、 isNaN() 関数を使用させる |
ルール | 概要 |
---|---|
cyclomatic-complexity | サイクロマティック複雑度の分析と閾値を適用する |
deprecation | デプリケート API の 使用を警告する |
eofline | ファイルが改行で終わるようにする |
indent | 指定するインデントルールを適用する |
linebreak-style | 指定する改行コードを適用する |
max-classes-per-file | ファイル内のクラス数を制限する |
max-file-line-count | ファイルの行数を制限する |
max-line-length | 1行の文字数を制限する |
no-default-export | ES6-style の デフォルト・エクスポートを禁止し、名前付きエクスポートを使用させる |
no-duplicate-imports | 同じモジュールからの複数インポートを禁止する |
no-mergeable-namespace | 同じファイル内のマージ可能な namespace を 禁止する |
no-require-imports | require() を 禁止し、新しい ES6-style import/export を 使用させる |
object-literal-sort-keys | オブジェクト・リテラルのキーは、アルファベット順に記述させる |
prefer-const | 変数への割り当てが1回に限られる場合、 const を 使用させる |
trailing-comma | 配列とオブジェクトのリテラルで最後にカンマを付けるかのルールを強制する |
ルール | 概要 | |
---|---|---|
align | 指定する要素 (e.g. 引数) を 垂直方向を揃えて整列して記述させる | |
array-type | 配列宣言を T[] もしくは Array の いずれかに統一させる | |
arrow-parens | Arrow-style 関数 の パラメーターで括弧を必須とする | |
arrow-return-shorthand | () => { return x; } を () => x と させる | |
binary-expression-operand-order | In a binary expression, a literal should always be on the right-hand side if possible. For example, prefer ‘x + 1’ over ‘1 + x’. | |
callable-types | コールシグネチャのみのインターフェース名やリテラル型は関数型を使用させる | |
class-name | クラスとインターフェース名はパスカルケース(アッパーキャメルケース)にさせる | |
comment-format | 1行コメントの書式設定ルールを強制する | |
completed-docs | Enforces documentation for important items be filled out. | |
encoding | UTF-8 エンコーディングを強制する | |
file-header | すべてのファイルに対して指定する正規表現にマッチするヘッダーコメントを強制する | |
import-spacing | import の キーワード間にスペースを入れることを強制する | |
interface-name | × | インターフェース名は I で 始まることを強制する |
interface-over-type-literal | 型リテラル( type T = {...} ) ではなく インターフェース名を使用させる | |
jsdoc-format | JSDoc の 基本形式ルールを強制する | |
match-default-export-name | デフォルト・インポートには、インポートする宣言と同じ名前の使用を必須とする | |
newline-before-return | ブロック内に return 以外の行がある場合、 return の 前に空行を必須とする | |
new-parens | new キーワードを使用してコンストラクタを呼び出す場合、括弧を必須とする | |
no-angle-bracket-type-assertion | 型アサーションに <Type> の 代わりに as Type を 使用させる | |
no-boolean-literal-compare | x === true のような、ブール・リテラルとの比較を警告する | |
no-consecutive-blank-lines | 1もしくは複数の空行を禁止する (デフォルトで 1つの空行を許可する) | |
no-irregular-whitespace | 文字列やコメントの外側にある不規則な空白を禁止する | |
no-parameter-properties | クラス・コンストラクタでのパラメーター・プロパティを禁止する | |
no-reference-import | <reference types="foo" /> の 使用を禁止する | |
no-trailing-whitespace | 行末尾の空白を禁止する | |
no-unnecessary-callback-wrapper | Replaces x => f(x) with just f . To catch more cases, enable only-arrow-functions and arrow-return-shorthand too. | |
no-unnecessary-initializer | var let destructuring initializer の undefined 初期化を禁止する | |
no-unnecessary-qualifier | Warns when a namespace qualifier (A.x ) is unnecessary. | |
number-literal-format | 小数点以下のリテラルは 0. で 始まり、末尾が 0 で 終わらないこと強制する | |
object-literal-key-quotes | Enforces consistent object literal property quote style. | |
object-literal-shorthand | 可能であれば ES6-style オブジェクト・リテラル の ショートハンドを強制する | |
one-line | 特定の予約語 (e.g. try の } と catch ) を同一行にさせるかのルールを強制する | |
one-variable-per-declaration | 複数の変数を同時定義することを禁止する | |
ordered-imports | import を アルファベット順に記述することを強制する | |
prefer-function-over-method | Warns for class methods that do not use ‘this’. | |
prefer-method-signature | インターフェースと型の定義を foo: () => void でなく foo(): void を 使用させる | |
prefer-switch | Prefer a switch statement to an if statement with simple === comparisons. | |
prefer-template | 文字列の連結ではなく、テンプレート式を使用させる | |
quotemark | 文字列リテラルを、一重引用符 または 二重引用符 の 指定する方に強制する | |
return-undefined | Void 関数 では return; を、値を返す関数では return undefined; を 使用させる | |
semicolon | すべてのステートメントの最後に一貫したセミコロンの使用を強制する | |
space-before-function-paren | 関数の括弧前に入れるスペースのルールを強制する | |
space-within-parens | 括弧内のスペースのルールを強制する | |
switch-final-break | switch の 最終節 が break で 終わるかのルールを強制する | |
type-literal-delimiter | Checks that type literal members are separated by semicolons. Enforces a trailing semicolon for multiline type literals. | |
variable-name | 変数名のルールを強制する | |
whitespace | 空白スタイルのルールを強制する |
TypeScript の コーディング量が足りていないので、どのようなコードを指しているのか想像がつかないものもかなりありました.
あと cyclomatic-complexity
が あるのがいいですね.
先に設定を悩むより、圧倒的なコーディング量を背景に、よろしくないコードを防ぐことをした方がよかったかもと思いつつ、理解が深まったのでよしとしましょう. 次は、設定を考えたいと思います.
Visual Studio Code で 使うために PortableGit を インストールしました. その際に 全体 gitignore を 設定したのですが、よくよく調べると、もっとよい設定方法がったので再設定します.
作業環境
GitHub 社 が 公開している github/gitignore というリポジトリ https://github.com/github/gitignore というのがあります.
様々なプログラム言語やフレームワークなどに応じた gitignore の テンプレートを提供してくれています. GitHub.com で リポジトリを作成する際や、作成した後から Web UI で gitignore を 追加する機能がありますが、その gitignore ファイルは このリポジトリから作られているとのことです.
アプリケーションを作る際などに、いつも参照させていただくのですが、よくよく見ていると Global というディレクトリがあり、こちらは OS や エディタなどのテンプレートが入っているとのことです. 知らなかった…
ちゃんと説明 Globally Useful gitignores - gitignore/Global at master · github/gitignore を 読まないとですね. ということで、こちらをもとに グローバル の gitignore を 再設定 します.
まず Windows.gitignore を 参照してみます. 2017年9月現在、以下の内容でした. 前回設定した Thumbs.db
だけとは大違いですね. 勉強になります.
1 | # Windows thumbnail cache files |
Visual Studio Code の 設定もありました. .vscode/
以下の Visual Studio Code 設定ファイル以外を ignore ですが、これでいいのかな?ちょっと意図を知りたいかも.
1 | .vscode/* |
Eclipse の 設定もあります. Eclipse で 関しているわけではないのですが、Eclipse エディタで編集したい部分があるなどで、Eclipse プロジェクトにしている場合があります. その場合は .project
や .settings
などの Eclipse 関連ファイルはコミットしたくないので、グローバル gitignore するのもよさそうです.
1 | .metadata |
利用する gitignore を 決めたら、グローバル gitignore を 作ります.
Powershell 3.0 から curl
こと Invoke-WebRequest
が 使えます. これでダウンロードすれば OK! (ただし使い方は Linux のとは異なるので注意)
対象が ひとつ の ファイルの場合は、コマンドプロンプトから以下のように実行します. ここでは Windows.gitignore
を ~/.gitignore
へ ダウンロードしました.
1 | c:\Temp> powershell curl -Uri https://raw.githubusercontent.com/github/gitignore/master/Global/Windows.gitignore -OutFile ~/.gitignore |
複数のファイルを結合する場合は、PowerShell を 起動してからコマンドを実行します. ここでは Windows.gitignore
と Eclipse.gitignore
と VisualStudioCode.gitignore
を 結合しました.
1 | c:\Temp> powershell |
複数ファイルを結合して使う場合に、コマンドを複数発行すればよいのですが ちょっと面倒だなぁという時は gitignore.io というサービスが自動で作ってくれます. なんと 名だたる企業が使っている ようです(が、企業ロゴが1枚画像で企業へのリンク無しなんだよなぁ…)
Web から使う場合は、 https://www.gitignore.io/ へ アクセスします.
画面中央のテキストボックスに gitignore したいテンプレート名前を入れていき、[Create] ボタンをクリックします.
自動生成された gitignore の 内容が出力されるので、コピー&ペーストします.
また、自動生成された gitginore 画面 の URL を 使うことでコマンドラインからも取得できます. キーワードをカンマでつなぐのですが、URL Encode するので %2C
で つなぎます.
1 | c:\Temp> powershell curl -Uri https://www.gitignore.io/api/windows%2Ceclipse%2Cvisualstudiocode -OutFile ~/.gitignore |
ヘルプや、指定できるキーワードのリストは PowerShell から 以下のように実行します.
1 | c:\Temp> powershell |
さらに Command Line Docs - gitignore.io には、公式のコマンドライン実行法について説明があります. スクリプト化しておくと便利なのかもしれませんが、 curl
だけでも大変ありがたいです.
gitignore.io-san, thank you for the wonderful service!!
github/gitignore リポジトリの Global ディレクトリ発見から、便利なサービスにまでたどり着くことができ、開発環境を作る際の幅広がりました. 自分が知っていることをすぐに使えることも必要ですが、他にも良いやり方は無いのかと疑問を持って調べる習慣も大事ですね. Global ディレクトリに気づかなかったのはホント不覚である…
今回は グローバル gitignore の 自動生成でしたが、アプリケーション用の gitignore も 同じことができるので、これからは自動生成でやった方が良いですね.
実際に使うにあたっては、グローバル gitignore は 自動生成後に編集.
アプリケーション用にはプロジェクトなり組織共通の gitignore を 管理するリポジトリを作って、先にそのファイルをダウンロードして、gitignore.io 自動生成を追記させるような感じでしょうか.
言語やフレームワークの gitignore を 自動生成させるとすると、独自追加部分だけが残り、だいたい どのリポジトリも同じものを追加すると思われるので、Git で 管理・共用化して、自動生成だけにするのがよいのかもと思ったりも… 今度やってみよう.
]]>TypeScript の tsconfig.json について検討 を 続けています. 今回はコンパイル・オプションについて考えます.
作業環境
TypeScript で Hello World では、Visual Studio Code の 公式ドキュメント の tsconfig.json を基に作成し、最小限のコンパイル・オプションを考え、ECMAScript の 最新に合わせた形になりました.
1 | { |
続いて、TypeScript の tsconfig.json を 考える では、コンパイル対象のソースファイルを指定する方法として files
と include/exclude
を 考え、とりあえず TypeScript 公式ドキュメント の include/exclude
サンプル を 使うことにしました.
1 | { |
コンパイル・オプションは最小限の設定しか見ていなかったので、しっかりと確認したいと思います.
TypeScript 公式ドキュメント の Compiler Options は https://www.typescriptlang.org/docs/handbook/compiler-options.html に なります.
ざっと 70個ぐらいのオプションがあるようで… とりあえず 使いそう or 要検討 なところをピックアップしたいと思います.
tsc --init
で 作られる tsconfig.json
が カテゴリー別に整理されているので、それに合わせて検討します.
"target": "es2017"
は、前回検討の通り 最新の es2017
にします."module": "commonjs"
は、実行環境の Node.js に 合わせて commonjs
にします"lib": []
は、コンパイルに含めるライブラリー、必要になったら都度追加します"declaration": true
は、型定義ファイル *.d.ts
を 生成するので使用します"sourceMap": true
は、デバッガー等のツール連携で使用します"outDir": "./dist"
は、コンパイル結果などの出力先ですが、命名に悩みつつ distribution
で dist
かな…"removeComments": true
は、コンパイル後もコメントを保持する必要はないので、削除します.※ outDir
は 悩ましいところです. 一般的なルールが欲しい… GitHub を 見ていると OutDir
や out
が 多いよう感じました.
"strict": true
noImplicitAny
, strictNullChecks
, noImplicitThis
, alwaysStrict
) を 有効化するので使います.strict
だけで賄えます.基本厳しくチェックなので、すべて true
に します.
"noUnusedLocals": true
は、未使用のローカル変数 を エラー報告します"noUnusedParameters": true
は、未使用のパラメーター を エラー報告します"noImplicitReturns": true
は、不正確な return
を エラー報告します"noFallthroughCasesInSwitch": true
は、 case
文 の フォールスルー を エラー報告しますおそらく types
で パッケージを指定するぐらいです.
ソース・マッピングに関する設定を変更する場合に設定するようですが、使わなそうです.
実験用. とはいえ、 experimentalDecorators
は 使いたいです.
Decorators を 使えるようにするもので、 2017年8月現在で Stage 2 であり、今後仕様が変わるかもしれませんが、フレームワークなどで使ったりするので、 true
に しておきます.
tsc --init
で 出力されていないけど、設定した方がよさそうなもの.
"newLine": "LF"
は、デフォルトがプラットフォーム依存なので明示しておきます"forceConsistentCasingInFileNames": true
は、ファイルの大文字小文字の違いをエラー報告します前回と合わせて、こんな感じでしょうか. まずは これで始めたいと思います.
1 | { |
List で チェックするような項目もコンパイラーでやってくれるのですね. 差異が分からないので、とりあえず厳しく設定してみました.
ディレクトリ系は相変わらずの悩みどころです. どこかにべスプラ的は話がないかなぁ…