Python で Raspberry Pi の USB を制御する

## Python で Raspberry Pi の USB を制御する
### 1. Spec
##### 1-1. ハード面

| アイテム | 詳細 |
|:-|:-|
| Raspberry Pi  | Raspberry Pi 3 Model B+  |

##### 1-2. ソフト面

| 内容 | バージョン |
|:-|:-|
| Raspberry Pi Imager  | v1.6.2  |
| Raspberry Pi OS (32-bit)  | リリース日：2021-05-07  |
| Kernel  | 5.10  |
| (補足)Raspbian  | 10.10  |
| Python | 3.9.0 64bit  |
| Visual Studio Code | 1.59.1  |

##### 1-3. 開発環境

+ Visual Studio Code

| アイテム | バージョン |
|:-|:-|
| バージョン  | 1.59.1 (user setup)  |
| コミット  | 3866c3553be8b268c8a7f8c0482c0c0177aa8bfa  |
| 日付  | 2021-08-19T11:56:46.957Z  |
| Electron  | 13.1.7  |
| Chrome  | 91.0.4472.124  |
| Node.js  | 14.16.0  |
| V8  | 9.1.269.36-electron.0  |
| OS  | Windows_NT x64 10.0.19042  |
| Python | 3.9.0 64bit  |

+ Raspberry Pi 側　(Thonny Python IDE)

| アイテム | バージョン |
|:-|:-|
| Python  | 3.7.3  |

※ Thonny Python IDE ではインデントなどが書きづらいので、
PC の Visual Studio Code でコードを書きつつ、Thonny Python IDE にコピペ。

### 2. Python のプログラミング
#### 2-1. プログラムを書きつつ Python の勉強。
今回やりたいことは以下。

1. Raspberry Pi の USB を、コマンドではなくPythonで制御したい。
1. 10分毎に15秒ライトを光らせたい。

ちなみに、コマンドについては以下を参照。

https://qiita.com/Colours/items/e1efd5bf335c03419c29

#### 2-2. 仕様モジュールを決定
時間取得用に

+ `time` モジュール
+ `datetime` モジュール

定期的に実行したいので、

+ `schedule` モジュール

Raspberry Pi のコマンドを使用するためのモジュールが

+ `os` モジュール

#### 2-3. モジュールの準備
`schedule` モジュールを使うために、ターミナルから
`pip install schedule` を使用。
しかし、Raspberry Pi の Thonny も、Visual Studio Code も、走らせるとエラーが発生。

Visual Studio Code の方では、

```python
Import schedule Could not be resolved
```
Thonny では、

```python
Python 3.7.3 (/usr/bin/python3)
>>> %Run RP_usb_ctrl.py
Traceback (most recent call last):
  File "/home/pi/RP_usb_ctrl.py", line 14, in <module>
    import schedule
ModuleNotFoundError: No module named 'schedule'
```

以下のサイトを参考に、

https://aburi6800.hatenablog.com/entry/2020/11/15/015329

##### 2-3-1. VSCode の設定
ファイル > ユーザー設定 > 設定
　> 拡張機能 > Pylance > `Python > Analsys: Extra Paths` の「項目の追加」から
`./source` を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/05c920bc-65da-2831-a027-309f4f3c5a6a.png)
　> VSCode を再起動。
import 文は変更せずともそのままで大丈夫でした。

##### 2-3-2. Thonny Python IDE の設定
一度、
`sudo pip install schedule`
を行いましたが、改善されず、こちらを見て、

https://www.raspberrypi.org/forums/viewtopic.php?t=291059

`sudo apt install python3-schedule`
このコマンドでエラーが無くなりました。

### 3. 最終的なコード

```python:RP_usb_ctrl.py
#!/usr/bin/env python

# ------------------------
#   モジュールインポート
# ------------------------
import time
# 時間モジュール : 処理時間の計測とか
import datetime
# Pythonで日付や時間を扱うためのモジュール
import os
# OSに依存しているさまざまな機能を利用するためのモジュール
import schedule
# 定期実行したいモジュール

# ------------------------
#   関数定義
# ------------------------

# USB-ON
def USB_ON():    
    print("USB-ON")
    os.system("sudo hub-ctrl -h 1 -P 2 -p 1")
    return

# USB-OFF
def USB_OFF():    
    print("USB-OFF")
    os.system("sudo hub-ctrl -h 1 -P 2 -p 0")
    return

# ------------------------
#   繰り返したい関数
# ------------------------
def job():
    now_time = datetime.datetime.now()
    print("現在時刻 : ", now_time)

    # USB-ON
    USB_ON()

    time.sleep(15)

    # USB-OFF
    USB_OFF()

    return

# ------------------------
#   定期実行
# ------------------------
def main():
    # 10分毎に実行
    schedule.every(10).minute.do(job)

    while True:
        schedule.run_pending()
        time.sleep(1)

if __name__ == "__main__":
    main()
```

以上で無事に USB のライトを ON-OFF することが出来ました。

### 4. 参考にさせて頂いたサイト

+ #!/usr/bin/env python について

https://techacademy.jp/magazine/22254

+ timeモジュール

https://www.sejuku.net/blog/23955

+ datetimeモジュール

https://techacademy.jp/magazine/22812

+ strftime関数

https://techacademy.jp/magazine/18883

+ strptime関数

https://techacademy.jp/magazine/33867

+ schedule モジュール

https://qiita.com/Kai-Suzuki/items/0c5c0e5cbdb4075fe482

https://miyabikno-jobs.com/python-schedule-library/

+ sleep関数

https://www.fenet.jp/dotnet/column/language/python/7837/

+ osモジュール

https://deviceplus.jp/hobby/raspberrypi-comfortable-space-device-04/

https://www.sejuku.net/blog/67787

+ `if __name__ == '__main__':`

https://blog.pyq.jp/entry/Python_kaiketsu_180207