Raspberry Piに再起動とシャットダウン([2019/01/14追記]、起動・ブート)用のボタンを実装する話。
ラズパイ2Bをサーバとして導入してから約3年、ssh接続、常時起動ではなく、都度、起動、ログイン・シャットダウンさせています。
そんな自身は、ラズパイ用のshutdownボタン情報を見かけても気にも留めなかったのですが、いざ、ラズパイでスマートスピーカーを作ってみると、なるほど、あった方がよいよね...。
sshすればよい話だけど、当然、パソコンを起動していない時も多々あるわけだから。
ん?スマートスピーカーに再起動は要らなかったか?まぁ、いいか。
Raspberry Piでスクリプトといえば、Pythonみたいな空気になっているっぽいし、それらしいのを探すと当たり前のようにpythonなので流れに身を任せることに。
が、RPI.GPIOライブラリを使っているものが多く見受けられますが、書き方がマチマチ、ならば元をたどるかとpypi.orgに行くとraspberry-gpio-pythonを見ろとあるも内容が薄過ぎてさっぱりわかりません...。
Raspbian Stretch環境でdpkg -l | grep gpioするとGPIO関連でインストール済みなのは、python-rpi.gpioだけっぽい。
apt-cache search gpioしてリポジトリを見るとgpiod、python-gpiozero/python3-gpiozero、pigpio/python-pigpio/python3-pigpioなどがあり、pigpioはデーモンらしいし、python3と明示してあるのは...ということでpython3-gpiozeroか、それじゃとgpiozeroで検索するとドキュメントもあったため、これに決定。
1.Installing GPIO Zeroの通りインストール。
ざっと読んでみるとどうもgpiozeroはラッパにもなっているようでRPI.GPIOが使えるところは、これで済ます仕様である模様。
ただし、gpiozeroにおけるGPIOピン番号は、BOARD/BCMの2通りあるRPI.GPIOとは異なり、RPI.GPIOで言うところのBCMのみとなる点は要注意。
まさに2.8.Shutdown buttonサンプルがあり、LED周りも眺めつつ、プログラムは、こんな感じにしてみました。
GPIO番号もリンク先ページ上方に図示されており、至れり尽くせり。
ジャンパワイヤ接続で3本圧着状態を想定し、一列で他と被らず、Groundピンも近い、後で何かを追加するにしても邪魔にならない端っこのGPIO16/GPIO20/GPIO21を使うことにしました。
たいてい*BSD/PC-UNIX/Linuxの再起動コマンドには、shutdown -r now/reboot、電源断には、shutdown -h now/halt/poweroffがあり、shutdownの-rはreboot、-hはhalt。
ここでは、rebootとpoweroffコマンドを使うことにしました。
LED1つで、poweroffでは、一定時間、LED点灯、rebootでは、LED点滅として目視確認できるようにしました。
check_call文に疑問はなく、単にスクリプト自体を確認するだけなら、2行あるcheck_call行をコメントアウト、それぞれprint文でも入れておくとよいかと。
pause()しっぱなしでデーモンとして登録するのってありか?とも思いましたが、デーモンってそんなもんか...、やってみたら、機能したし、よしとしました。
尚、スクリプト単独で確認する際は、poweroff/rebootにsudoを要しますが、後述のようにsystemdサービスを登録すれば、root起動となるため、その際は、sudoがなくとも機能すると思われます。
先日、ラズパイスマートスピーカーを自動起動させるにあたり、公式ドキュメントを見ながらsystemdサービスファイルを書きました。
が、今回は、公式ドキュメントではわかりそうもなく、探した結果、Q&Aの回答にある.serviceファイルをそのまま使わせて頂いたところ、うまく、機能しました。
systemctl startし、statusを確認、よければ、enableして再起動すれば、reboot/shutdownボタンが機能するようになります。
ちなみに構成ファイルを編集したら、systemctl stop、systemctl disable、systemctl daemon-reload、systemctl start(現在のログイン時のみ有効)/systemctl enable(次回以降の起動時に有効)。
現在のログイン状態のまま、確認したいわけでないのならstartは不要。
とりあえず、ブレッドボード上に回路を仮実装し、検証を行ないました。
材料は、ラズパイx1式、タクトスイッチx2個、LEDx1個、抵抗220Ωx1個、ジャンパワイヤ適量、ミニブレッドボードx2個。
ラズパイボードには、USB HDDブートしているパソコンとして使うべく買ったRaspberry Pi 3 Model B+/OS Raspbian Stretchを使用。
ラズパイの下にある黒いのが、バスパワーのUSB HDD(モバイルバッテリではない)。
USBメモリブートという違いはあれど自作スマートスピーカーもRaspberry Pi 3 Model B+/OS Raspbian Stretchなのでそのまま使えます。
尚、自作のスマートスピーカーは、あえてクラウドは一切使っていないものの、Web APIやRSSの利用、直接IP指定しているものなど一部機能においては、インターネットにつながっていること前提であるため、LANに接続する必要があります。
自身は、取り回しが煩雑で制約もある有線・LANケーブルではなく、ラズパイ3B+内蔵WiFiから宅内の無線LANアクセスポイントに接続しています。
生まれつき変わらぬ雑さには、我ながら、ほとほと呆れますが、自身初となるユニバーサル基板実装でボタンスイッチを作ってみました。
材料は、100均で買った5個108円の留具付きケース 1個、ユニバーサル基板5cmx7cm 1個、足の短い表面実装用タクトスイッチ 2個、LED 5mm 1個、220Ωカーボン抵抗 1個、被覆付き錫メッキ線 適量。
もちろん、ハンダ用にハンダゴテとはんだ(0.6mm)も使ったし、ケースよりやや大きいユニバーサル基板の2辺を適量切断するにあたり、両面に切り目を入れるナイフと切りつつ、折るためにニッパも使いました。
また、ケース穴あけに穴あけ加工用にしてあるハンダゴテ、LEDの脚の保護用にストローを適度な長さに切ったもの、ボタンにコテのおまけかハンダ(1mm)が入っていた円柱ケースのフタ(赤)1個、同じくケース胴体(透明)の底部をフタと同じくらいのサイズに切り取ったもの1個、固定及び嵩増し用にグルー及びグルーガンも使いました。
よって凝固したグルーがタクトスイッチを押す構造になります。
雑なだけに適当にやったわけですが、ボタン間に、また、それぞれのボタン底部とタクトスイッチ間に適度な距離を保てば、ケースフタの柔軟性も手伝ってスイッチを押下できます。
ちなみに両方のボタンを同時に押せば別だし、経年劣化も考慮しようはないものの、現時点では、何れのボタンを押しても他方が同時に押されることはありません。
ユニバーサル基板は、両面タイプと片面タイプを持っていますが、初めてということもあり、ケチって片面タイプを使い、回路が平易だったので雑な割に一発で無事通電し、機能させることができました。
尚、片面タイプのユニバーサル基板の場合、半田面が裏に来るのでしょうが、以前間違って届き、そのまま受理した足の短いSMD タクトスイッチを使った為、半田面を上にせざるを得ませんでした。
動作確認には、スイッチ2個のプラスには、ラズパイからのジャンパワイヤ オスを手で接触させる恰好で、プラス側としたLED用抵抗は、足を出してある為、ワニグチクリップケーブルでラズパイ側に接続したジャンパワイヤとつなぎました。
動作確認時すら、手持ちの20cmのジャンパワイヤを2本つなげたこともあり、1本だけでは短すぎる、数本つなげるにしても強度に不安があり、スイッチまでの配線をどうしたものか勘案中。
が、今のところ、両端はジャンパワイヤにし、ユニバーサル基板上には、3連に切った1列ピンソケット(メス)を実装するつもりです。
設置場所の自由度からして本来ならこの自作スイッチを無線化したいところもスマートスピーカーがWiFi接続、Bluetoothと同時使用は、干渉して不具合につながるケースもあるらしい。
ということは、BLEも、マウスやキーボードによくある2.4GHz無線も同じことかもしれない...。
もし、仮に問題ないとして電源確保となると電池駆動、CR2302を使うにしても、この自作スイッチに追加するのは厳しいというか面倒でもあるし、今回は見送ろうと思います。
うわっ、GND入れて4ピンじゃん...1ピン分忘れた...昨日の時点で「3本圧着状態」とか「3連」とか言ってるし...ボケっぷりも昔から...。
仕方なくGND用の穴を別途開け、GNDは直ではんだ付することにしましたが、とりあえず動作確認もできました。
追加材料としては、ピンソケットメス(2本のラジオペンチを使って3ピン分折ったもの)、ラッピングワイヤーなども持っていますが、今回は、ピン抜けなどで大量に修理部品在庫としてあるジャンパワイヤを細切れしたものをハンダ用配線、片側を切ったジャンパワイヤをGNDピンとして使いました。
穴あけには、キリとナイフ、細い平ヤスリ・丸ヤスリを使用。
よく考えたら、起動スイッチも要るよね?より正確に言うと自作シャットダウンボタンを押した後、起動するスイッチ。
今のところラズパイを持ち歩くことは想定しておらず、そもそも完全に電源断すべく、どのラズパイもスイッチ付き電源タップにつなぐ前提です。
よって電源タップのスイッチのON/OFFで事足り、シャットダウン後、すぐ起動するにしても電源タップスイッチのOFF => ONでもよいわけですが、どっちでもいけるということで。
検索してみるとWake from haltやSafe Modeを発見、どうやらSafe Modeと呼ぶらしい!?
それらリンク先によれば、Raspberry Pi 1(初期)の時代から、それらしいものはあったようで、ある時点からは、BOARD5ピン(BCM GPIO3)とBOARD6ピン(Ground)を一瞬接続すれば、起動できるらしいことが書いてあります。
早速、試してみるとhaltだけでなく、poweroffでもshutdown -h now後でも起動できることを確認。
Groundは、他にもあり、BOARD6である必要があるはずはない。
ちなみに自身は、3B+を使っており、冷却ファンをBOARD4(5V)/BOARD6(Ground)でBOARD6ピンは使用済みだったため、GNDには、BOARD9ピンのGroundで検証しました。
尚、BCM GPIO3(BOARD 5)ピンは、SCLピンとしても割り当てられており、I2C通信デバイスを使う場合には、分岐するなど考慮が必要です。
結果、自身は、I2Cデバイスを使う予定はないため、終了はpoweroffのままとしました。
これに伴い、前段のプログラム及び配線するピンをGPIO3/GPIO4/Ground(BOARD9ピン)/GPIO17(筆者自身専用メモ:橙/青/灰/黃)に変更することにしました。
このpoweroff後の起動(boot)の機能については、プログラムに書く必要は(書こうにも書きようが)ありません。
逆に言うとブートボタンを押したことを目視確認するためにLEDを点けることはできないし、ボタン押下時間を設定することもできません。
プログラム上GPIO3につないだ自作シャットダウンボタンを押してシャットダウンした状態で同じボタンをちょっとでも押すとGPIO3がGroundにつながるため、復帰・再開・ブートします。
本当に起動しているかどうかは、ラズパイのLEDを眺めるなり、PCなどから起動前後でnmapの結果の違いを確認するなり、SSHやVNC経由でログインしてみたり、例えば、スマートスピーカーで起動音や起動メッセージが流れるなら、それを以て確認したりすることになります。
シャットダウンしただけでは、通電状態であり、ラズパイ3B+では、ほぼ必須の冷却ファンが停止しないし、自作スマートスピーカーだとスピーカーの電源も落ちません(一度OFFにはなるも、またONになる)。
よって自身は、前述の通り、スイッチ付き電源タップを使い、ガジェットを使わないとわかっている時には、最終的にこのスイッチで電源を落とす運用とするつもりです。
なんと、リンク先は2019年のことの模様もDebian/Raspbian/Raspberry Pi OSが対応したのは?極々最近のことかとは思いますが、システムにとって超重要なスクリプトは?ホームディレクトリとかではなく、/usr/local/binなどに置かなければならなくなったらしい。
このラズパイリブート・シャットダウンスクリプトも対象だった模様で、そんなバカな...と思いつつ、このスクリプトをホームディレクトリから/usr/local/binに移してみたら、それまでのことが嘘のように正常に機能するようになりました。
確かに安全考えると当たり前ですかね。
今回、ブート・システム両用ブートUSBメモリのシステムがおかしくなってupgrade前後で起きたことからシステムに起因と踏み、同じUSBメモリにイチから構築した後、数日で他の検証がてらSSDにddしたりしてラズパイリブート・シャットダウンのスクリプトとsystemdサービスファイルの作成を忘れて、自作ボタンが使えなくなった原因がこれだと判明。
これって先月末頃の話で、それまでは自作ボタンも使えてた...はず。
そして今日、このラズパイリブート・シャットダウンのスクリプト作成、systemdサービスファイルの作成、実行をしてみてsystemd startしたら[Failed at step EXEC spawning スクリプト]とかエラーが出てハマり、原因を探って先のリンクに行き着き、/usr/local/binに移動してみたら、あっさり機能した次第。
ただ、重要度のくくりがあるようで、同じくsystemdから呼んでいる自作スマートスピーカーは数年前から、また、昨日登録したばかりの自前のIPカメラから映像配信通知を受信・動画/画像としてサーバに保存する用のスクリプトは、ホームディレクトリにおいてあっても問題なく、正常に機能しています。
初Fritzingでユニバーサルボード(ユニバーサル基板)図作ってみました。
ここでは、ユーザー名pi、ホスト名raspberrypiともにRaspberry Piデフォルトにしてありますが、セキュリティ面から、事前にというか初期段階でパスワードraspberryはもちろんのこと、少なくともユーザー名は、できればホスト名も変更しておくのが賢明でしょう。