RaspberryPiのUSBポートの電源On/Offを制御する

#はじめに
RaspberryPiのUSBポートの電源On/Offを操作してみました。

[前回の記事](https://qiita.com/masatarou/items/ceff06f9515ed224e4e7)でBlynkサーバー経由でRaspberryPiとスマートフォンを接続したので、スマートフォン側から操作して電源操作をしています。

#使用した物

- Androidスマートフォン
- Raspberry Pi3 B+
- [USB-HUB（BUFFALO BSH4AE12BK）](https://www.amazon.co.jp/iBUFFALO-%E9%9B%BB%E6%BA%90%E9%80%A3%E5%8B%95%E7%AF%80%E9%9B%BB%E6%A9%9F%E8%83%BD%E4%BB%98%E3%81%8D-4%E3%83%9D%E3%83%BC%E3%83%88%E3%82%BB%E3%83%AB%E3%83%95%E3%83%91%E3%83%AF%E3%83%BC%E3%83%8F%E3%83%96-%E3%83%96%E3%83%A9%E3%83%83%E3%82%AF-BSH4AE12BK/dp/B01GPLB2VI/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=BSH4AE12BK&qid=1585134860&s=computers&sr=1-1) ★重要（理由は後述）
- [USB扇風機](https://www.amazon.co.jp/gp/product/B010UTIP7K/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1)

#使用機器の全体像
上記の使用機器の全体像はこのような感じです。
![全体像.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572384/5b42df85-7311-3ab4-b505-74a43f5ccd08.jpeg)
スマートフォンとRaspberryPiは同じローカルエリア内で接続をしており、それとBlynkサーバーが繋がっているイメージです。
RaspberryPiと今回制御するUSB-HUB/USB-FANを繋いでいます。

#事前準備
###1．Blynkの導入と接続
以降のやり方はBlynkを使用したやり方なので、スマートフォン／RaspberryPiの双方でBlynkのインストールと接続が必要になります。

やり方はこちらを参照ください。
↓↓↓
[Blynkを使ってRaspberryPiとスマートフォンを接続する](https://qiita.com/masatarou/items/ceff06f9515ed224e4e7)

###2．Blynk のプログラム修正
初期設定ではスクリプトが扱いづらいので下記サイトを参考にして変更しています。

http://blog.livedoor.jp/victory7com/archives/48432885.html

その結果、ウィジェットの設定とRaspberryPi側のスクリプトの関係性は以下の図のようになっています（※同サイトから画像を引用）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572384/97038fb3-c51b-99db-db41-fae05197e841.png)

#実装
###スマートフォン側の作業
スマートフォン側ではBlynkのプロジェクトにウィジェットとスクリプトに紐づくピンを選択します。
![blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572384/30635b76-fe54-ad5f-ed84-87ca0caa8326.jpeg)

【左】ウィジェットをタップしウィジェット設定を開く
【中】今回はボタンなので、ボタンを押したときに紐づくピンを選ぶためタップ
【右】ピンの種類とピンの番号を選択する

※ピンの種類はDigital（GPIOポート）／Virtual（スクリプト）から選べますが、今回はスクリプトと紐づけたいため、後者を選択
※ピンの番号はスクリプトの名称と紐づける番号なので、何でもいいですがV10にしました。


###RaspberryPi側の作業
####1．USBポートを制御するためのツール（hub-ctrl）を導入

```
pi@raspberrypi:~ $ sudo apt-get install libusb-dev
pi@raspberrypi:~ $ git clone https://github.com/codazoda/hub-ctrl.c
pi@raspberrypi:~ $ cd hub-ctrl.c
pi@raspberrypi:~/hub-ctrl.c $ gcc -O2 hub-ctrl.c -o hub-ctrl-armhf-static -lusb –static
pi@raspberrypi:~/hub-ctrl.c $ sudo cp hub-ctrl-armhf-static /usr/local/bin/hub-ctrl
```
※補足
１行目：libusbをインストール
２行目：Githubから「[hub-ctrl.c](https://github.com/codazoda/hub-ctrl.c)」をダウンロード
４行目：hub-ctrl.cのインストール

####2．USBポートの接続状況を確認する
「lsusb」コマンドを実行するとUSBポートに接続しているデバイスとそのBus番号とDevice番号が返されます。
今回USB-HUBが操作対象なので、デバイス名が「Genesys Logic」であることを確認します。

```
pi@raspberrypi:~ $ lsusb

Bus 001 Device 005: ID 046d:c016 Logitech, Inc. Optical Wheel Mouse
Bus 001 Device 004: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 006: ID 0424:7800 Standard Microsystems Corp. 
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

####3．USB-HUBの電源ON/OFFのシェルスクリプトを作成する
ウィジェット設定でピンの番号を「V10」にしたため、スクリプトのファイル名に「V10」としています。

```
pi@raspberrypi:~ $ sudo vi /home/pi/blynk/BLYNK_WRITE_V10.sh
```

スクリプトの中身はこのような内容にしています。

```/home/pi/blynk/BLYNK_WRITE_V10.sh
#!/bin/sh

HUB=`/usr/bin/lsusb -v 2>/dev/null | grep ^Bus | grep "Genesys Logic, Inc. Hub" | head -1`
BUS=`echo $HUB | awk '{print $2}'`
DEV=`echo $HUB | awk '{print $4}' | sed -e "s/\(.*\)\:/\1/p;d"`

for i in 1 2 3 4
do
     /usr/local/bin/hub-ctrl -b $BUS -d $DEV -P $i -p 0
done
```

#####スクリプトの補足

<dl>
  <dt>デバイス情報の設定（３行目）</dt>
  <dd>lsusbの命令の結果を、デバイスの名称で抽出し変数HUBにセットする。</dd>
  <dt>Bus番号の設定（４行目）</dt>
  <dd>HUBに設定された２番目のフィールドを変数BUSにセットする。</dd>
  <dt>Device番号の設定（５行目）</dt>
  <dd>HUBに設定された４番目のフィールドを文字の置き換えをして変数DEVにセットする。</dd>
  <dt>for文（７行目）</dt>
  <dd>USB-HUBのポートが４つあるので、４回ループさせている。</dd>
  <dt>hub-ctrlコマンド（９行目）</dt>
  <dd>「-b」は対象のBus番号、「-d」は対象のDevice番号、「-P」はポート番号を指定する。</dd>
  <dd>最後の「-p」は電源供給On/Offの指定で、「0」(Off)／「1」(On)のいずれかを指定する。</dd>
</dl>


これでウィジェットで指定したピンの番号に相対するスクリプトができたため、スマートフォン側でボタンを押せばこのスクリプトが起動します。
その結果、USB扇風機の電源のOn/Offを切り替えができます。


#USBポートの電源操作の補足
RaspberryPiの昔のバージョンだと本体のUSBポートを個別に電源制御できるようでしたが、バージョンが上がったため不可能になりました。

「Per-port power switching」仕様のUSB-HUBであれば制御可能ということでしたが、それに対応したHUBが現在販売されてません。
今回使用した**BUFFALOのBSH4AE12BK**であれば**USB-HUB単位に電源制御可能**ということで、これを利用することにしました。

#まとめ
ウィジェットで指定したピンとそれに紐づくスクリプトを作成すれば、スマートフォン側からスクリプトを実行させることができました。
まずは動かし方の基本を理解できたので、次は違うウィジェットを使って動かしてみたいです。

#参考リンク
- 第3回 CPUの温度/周波数/負荷状態を見よう - 連載 IoTサービス「Blynk」を使ってRaspberry Piをスマホからコントロールしよう（Raspberry Piブログ）
    - http://blog.livedoor.jp/victory7com/archives/48432885.html 
- Raspberry PiにUSB扇風機を接続してUSBポートをON/OFF制御する方法（きのこタイムズ）
    - https://kinokotimes.com/2017/03/07/usb-control-method-by-raspberry-pi/ 
- LinuxからUSB HUBの電源のON/OFFを制御してみる（memoメモ）
    - http://atotto.hatenadiary.jp/entry/linux-sugoi-usb-hub-power-ctrl
- RaspberryPI 3 Model B で USBポートの電源をON/OFFする（パソコン鳥のブログ）
    - https://iot-plus.net/make/raspi/rpi3-blynk-shutdown/
- クルマにバックカメラと液晶モニタを取り付けてみた：GL-AR150/OpenWRTとAmazon Dash ButtonとUSBハブを使って
    - https://qiita.com/somainit/items/db4d8fe760e3fb88905f