#author("2020-03-16T01:54:22+00:00","default:mizutu","mizutu")
[[私的AI研究会]] > SDK on RaspberryPi

* Assistant SDK (Python) の Raspberry Pi へのインストール [#k85e8bee]
#ref(画像一覧/20200209_142556_001s.jpg,right,around,25%,20200209_142556_001s.jpg)
#ref(画像一覧/20200216_092138_001s.jpg,right,around,25%,20200216_092138_001s.jpg)
#contents

#clear
** 事前準備 [#v91eeec8]

*** オーディオのテスト [#n58b2e79]
+ 録音および再生デバイスを見る。~
a. キャプチャハードウェアデバイスのリストでUSBマイクを見つけ、カード番号とデバイス番号を書き留める。~
 $ arecord -l
b. 再生ハードウェアデバイスのリストでスピーカーを見つけ、カード番号とデバイス番号を書き留める。~
 &color(red){3.5mmジャックには通常、Analogまたはbcm2835 ALSA(bcm2835 IEC958/HDMIではない)というラベルが付いていることに注意。};~
 $ aplay -l
+ ホームディレクトリ(~/)に .asoundrc の名前で新しいファイルを作成する。<card number>と<device number>を前のステップで書き留めた番号に変更する。
 $ vi .asoundrc
 
 pcm.!default {
   type asym
   capture.pcm "mic"
   playback.pcm "speaker"
 }
 pcm.mic {
   type plug
   slave {
     pcm "hw:<card number>,<device number>"
   }
 }
 pcm.speaker {
   type plug
   slave {
     pcm "hw:<card number>,<device number>"
   }
 }
+ 記録と再生が機能することを確認~
a. 再生音量を調整。~
 $ alsamixer
または~
 $ amixer sset PCM 80% -c0
b. テストサウンドを再生。確認できたら、Ctrl + Cを押す。これを実行しても何も聞こえない場合は、スピーカーの接続を確認。~
 $ speaker-test -t wav
 speaker-test 1.1.8
 
 再生デバイス: default
 ストリームパラメータ: 48000Hz, S16_LE, 1 チャネル
 WAV ファイル
 レート 48000Hz (要求値 48000Hz)
 バッファサイズ範囲 512 ? 65536
 ピリオドサイズ範囲 512 ? 65536
 最大バッファサイズ 65536 を使用
 ピリオド数 = 4
 period_size = 16384 で設定
 buffer_size = 65536 で設定
  0 - Front Left
 ピリオド時間 = 0.358402
  0 - Front Left
 ピリオド時間 = 1.371160
  0 - Front Left
 ピリオド時間 = 1.360027
  0 - Front Left
 ^C
c. 短いオーディオクリップを録音。~
 $ arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw
d. 再生して記録を確認。何も聞こえない場合は、で録音ボリュームを確認する。~
 $ aplay --format=S16_LE --rate=16000 out.raw
録音と再生が機能している場合、オーディオの設定は完了。そうでない場合は、マイクとスピーカーが正しく接続されていることを確認する。

** Raspberry Pi での導入準備 [#b33ac3f1]
-「Python3」と開発環境仮想化できる「venv」をインストール
 pi@raspberrypi:~ $ sudo apt install python3-dev python3-venv
 パッケージリストを読み込んでいます... 完了
 依存関係ツリーを作成しています                
 状態情報を読み取っています... 完了
 python3-dev はすでに最新バージョン (3.7.3-1) です。
 python3-dev は手動でインストールしたと設定されました。
 python3-venv はすでに最新バージョン (3.7.3-1) です。
 python3-venv は手動でインストールしたと設定されました。
 アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。

- 仮想環境を作成
 pi@raspberrypi:~ $ python3 -m venv env

- 仮想環境のパッケージをアップデート
 pi@raspberrypi:~ $ env/bin/python -m pip install --upgrade pip setuptools wheel
 Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
 Collecting pip
   Downloading https://files.pythonhosted.org/packages/54/0c/d01aa759fdc501a58f431eb594a17495f15b88da142ce14b5845662c13f3/pip-20.0.2-py2.py3-none-any.whl (1.4MB)
     100% |████████████████████████████████| 1.4MB 273kB/s 
 Collecting setuptools
   Downloading https://files.pythonhosted.org/packages/3d/72/1c1498c1e908e0562b1e1cd30012580baa7d33b5b0ffdbeb5fde2462cc71/setuptools-45.2.0-py3-none-any.whl (584kB)
     100% |████████████████████████████████| 593kB 618kB/s 
 Collecting wheel
   Downloading https://files.pythonhosted.org/packages/8c/23/848298cccf8e40f5bbb59009b32848a4c38f4e7f3364297ab3c3e2e2cd14/wheel-0.34.2-py2.py3-none-any.whl
 Installing collected packages: pip, setuptools, wheel
   Found existing installation: pip 18.1
     Uninstalling pip-18.1:
       Successfully uninstalled pip-18.1
   Found existing installation: setuptools 40.8.0
     Uninstalling setuptools-40.8.0:
       Successfully uninstalled setuptools-40.8.0
 Successfully installed pip-20.0.2 setuptools-45.2.0 wheel-0.34.2

- 保存ライブラリのインストール
 pi@raspberrypi:~ $ sudo apt install portaudio19-dev libffi-dev libssl-dev libmpg123-dev
 パッケージリストを読み込んでいます... 完了
 依存関係ツリーを作成しています                
 状態情報を読み取っています... 完了
 libssl-dev はすでに最新バージョン (1.1.1d-0+deb10u2+rpt1) です。
 libssl-dev は手動でインストールしたと設定されました。
 以下の追加パッケージがインストールされます:
   libasound2-dev libjack-jackd2-dev libout123-0 libportaudiocpp0
 提案パッケージ:
   libasound2-doc portaudio19-doc
 以下のパッケージが新たにインストールされます:
   libasound2-dev libffi-dev libjack-jackd2-dev libmpg123-dev libout123-0 libportaudiocpp0 portaudio19-dev
 アップグレード: 0 個、新規インストール: 7 個、削除: 0 個、保留: 0 個。
 602 kB のアーカイブを取得する必要があります。
 この操作後に追加で 1,924 kB のディスク容量が消費されます。
 続行しますか? [Y/n] y
 取得:1 http://archive.raspberrypi.org/debian buster/main armhf libasound2-dev armhf 1.1.8-1+rpt1 [145 kB]
 取得:2 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf libffi-dev armhf 3.2.1-9 [159 kB]
 取得:3 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf libjack-jackd2-dev armhf 1.9.12~dfsg-2 [92.9 kB]          
 取得:4 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf libout123-0 armhf 1.25.10-2 [35.5 kB]
 取得:5 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf libmpg123-dev armhf 1.25.10-2 [54.9 kB]
 取得:6 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf libportaudiocpp0 armhf 19.6.0-1 [16.8 kB]
 取得:7 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian buster/main armhf portaudio19-dev armhf 19.6.0-1 [98.6 kB]
 602 kB を 4秒 で取得しました (149 kB/s)   
 以前に未選択のパッケージ libasound2-dev:armhf を選択しています。
 (データベースを読み込んでいます ... 現在 156865 個のファイルとディレクトリがインストールされています。)
 .../0-libasound2-dev_1.1.8-1+rpt1_armhf.deb を展開する準備をしています ...
 libasound2-dev:armhf (1.1.8-1+rpt1) を展開しています...
 以前に未選択のパッケージ libffi-dev:armhf を選択しています。
 .../1-libffi-dev_3.2.1-9_armhf.deb を展開する準備をしています ...
 libffi-dev:armhf (3.2.1-9) を展開しています...
 以前に未選択のパッケージ libjack-jackd2-dev:armhf を選択しています。
 .../2-libjack-jackd2-dev_1.9.12~dfsg-2_armhf.deb を展開する準備をしています ...
 libjack-jackd2-dev:armhf (1.9.12~dfsg-2) を展開しています...
 以前に未選択のパッケージ libout123-0:armhf を選択しています。
 .../3-libout123-0_1.25.10-2_armhf.deb を展開する準備をしています ...
 libout123-0:armhf (1.25.10-2) を展開しています...
 以前に未選択のパッケージ libmpg123-dev:armhf を選択しています。
 .../4-libmpg123-dev_1.25.10-2_armhf.deb を展開する準備をしています ...
 libmpg123-dev:armhf (1.25.10-2) を展開しています...
 以前に未選択のパッケージ libportaudiocpp0:armhf を選択しています。
 .../5-libportaudiocpp0_19.6.0-1_armhf.deb を展開する準備をしています ...
 libportaudiocpp0:armhf (19.6.0-1) を展開しています...
 以前に未選択のパッケージ portaudio19-dev:armhf を選択しています。
 .../6-portaudio19-dev_19.6.0-1_armhf.deb を展開する準備をしています ...
 portaudio19-dev:armhf (19.6.0-1) を展開しています...
 libjack-jackd2-dev:armhf (1.9.12~dfsg-2) を設定しています ...
 libffi-dev:armhf (3.2.1-9) を設定しています ...
 libout123-0:armhf (1.25.10-2) を設定しています ...
 libportaudiocpp0:armhf (19.6.0-1) を設定しています ...
 libasound2-dev:armhf (1.1.8-1+rpt1) を設定しています ...
 libmpg123-dev:armhf (1.25.10-2) を設定しています ...
 portaudio19-dev:armhf (19.6.0-1) を設定しています ...
 libc-bin (2.28-10+rpi1) のトリガを処理しています ...
 man-db (2.8.5-2) のトリガを処理しています ...
 install-info (6.5.0.dfsg.1-4+b1) のトリガを処理しています ...

- 仮想環境を有効化(アクティベイト)
 pi@raspberrypi:~ $ source ~/env/bin/activate
 (env) pi@raspberrypi:~ $
&color(green){以降、(env) $ のコマンドプロンプトの場合は仮想環境下にある。};

*** 仮想環境のコントロール [#j3fb34b4]
- Activate (有効化)
 pi@raspberrypi:~ $ source ~/env/bin/activate

- python のバージョン確認
 (env) pi@raspberrypi:~ $ python -V
 Python 3.7.3

- Deactivate (無効化)
 (env) pi@raspberrypi:~ $ deactivate

- 終了(無効化)確認
 pi@raspberrypi:~ $ python -V
 Python 2.7.16

- 参考サイト: [[venv: Python 仮想環境管理>+https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e]]

** Assistant SDK (Python) インストール [#dde35b69]
- Assistant Library のインストール (env)
 ※ [[Google Assistant Library 最新版>+https://pypi.org/project/google-assistant-library/]]
 (env) pi@raspberrypi:~ $ python -m pip install --upgrade google-assistant-library==1.0.1
 Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
 Collecting google-assistant-library==1.0.1
   Downloading google_assistant_library-1.0.1-py2.py3-none-linux_armv7l.whl (5.6 MB)
      |████████████████████████████████| 5.6 MB 9.5 kB/s 
 Collecting argparse<2,>=1.4.0
   Downloading argparse-1.4.0-py2.py3-none-any.whl (23 kB)
 Collecting google-auth<2,>=1.0.1
   Downloading google_auth-1.11.0-py2.py3-none-any.whl (76 kB)
      |████████████████████████████████| 76 kB 1.5 MB/s 
 Collecting requests<3,>=2.14.2
   Downloading requests-2.22.0-py2.py3-none-any.whl (57 kB)
      |████████████████████████████████| 57 kB 1.6 MB/s 
 Collecting pathlib2<3,>=2.3.0
   Downloading pathlib2-2.3.5-py2.py3-none-any.whl (18 kB)
 Collecting enum34<2,>=1.1.6
   Downloading enum34-1.1.6-py3-none-any.whl (12 kB)
 Collecting six>=1.9.0
   Downloading six-1.14.0-py2.py3-none-any.whl (10 kB)
 Collecting cachetools<5.0,>=2.0.0
   Downloading cachetools-4.0.0-py3-none-any.whl (10 kB)
 Collecting pyasn1-modules>=0.2.1
   Downloading pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB)
      |████████████████████████████████| 155 kB 639 kB/s 
 Requirement already satisfied, skipping upgrade: setuptools>=40.3.0 in ./env/lib/python3.7/site-packages (from google-auth<2,>=1.0.1->google-assistant-library==1.0.1) (45.2.0)
 Collecting rsa<4.1,>=3.1.4
   Downloading rsa-4.0-py2.py3-none-any.whl (38 kB)
 Collecting chardet<3.1.0,>=3.0.2
   Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
      |████████████████████████████████| 133 kB 2.5 MB/s 
 Collecting idna<2.9,>=2.5
   Downloading idna-2.8-py2.py3-none-any.whl (58 kB)
      |████████████████████████████████| 58 kB 1.7 MB/s 
 Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
   Downloading urllib3-1.25.8-py2.py3-none-any.whl (125 kB)
      |████████████████████████████████| 125 kB 3.1 MB/s 
 Collecting certifi>=2017.4.17
   Downloading certifi-2019.11.28-py2.py3-none-any.whl (156 kB)
      |████████████████████████████████| 156 kB 3.1 MB/s 
 Collecting pyasn1<0.5.0,>=0.4.6
   Downloading pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
      |████████████████████████████████| 77 kB 1.7 MB/s 
 Installing collected packages: argparse, six, cachetools, pyasn1, pyasn1-modules, rsa, google-auth, chardet, idna, urllib3, certifi, requests, pathlib2, enum34, google-assistant-library
 Successfully installed argparse-1.4.0 cachetools-4.0.0 certifi-2019.11.28 chardet-3.0.4 enum34-1.1.6 google-assistant-library-1.0.1 google-auth-1.11.0 idna-2.8 pathlib2-2.3.5 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.22.0 rsa-4.0 six-1.14.0 urllib3-1.25.8
 (env) pi@raspberrypi:~ $ 

- assistant SDK インストール &color(green){(時間がかかる)};
 (env) pi@raspberrypi:~ $ python -m pip install --upgrade google-assistant-sdk[samples]==0.5.1
 Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
 Collecting google-assistant-sdk[samples]==0.5.1
   Downloading google_assistant_sdk-0.5.1-py2.py3-none-any.whl (33 kB)
 Collecting google-auth-oauthlib[tool]>=0.1.0
   Downloading google_auth_oauthlib-0.4.1-py2.py3-none-any.whl (18 kB)
 Collecting sounddevice<0.4,>=0.3.7; extra == "samples"
   Downloading sounddevice-0.3.14-py2.py3-none-any.whl (30 kB)
 Requirement already satisfied, skipping upgrade: urllib3[secure]<2,>=1.21; extra == "samples" in ./env/lib/python3.7/site-packages (from google-assistant-sdk[samples]==0.5.1) (1.25.8)
 Collecting click<7,>=6.7; extra == "samples"
   Downloading click-6.7-py2.py3-none-any.whl (71 kB)
      |████████████████████████████████| 71 kB 214 kB/s 
 Collecting tenacity<5,>=4.1.0; extra == "samples"
   Downloading tenacity-4.12.0-py2.py3-none-any.whl (25 kB)
 Collecting google-assistant-grpc==0.2.1; extra == "samples"
   Downloading google_assistant_grpc-0.2.1-py2.py3-none-any.whl (21 kB)
 Collecting futures<4,>=3.1.1; extra == "samples"
   Downloading futures-3.1.1-py3-none-any.whl (2.8 kB)
 Requirement already satisfied, skipping upgrade: pathlib2<3,>=2.3.0; extra == "samples" in ./env/lib/python3.7/site-packages (from google-assistant-sdk[samples]==0.5.1) (2.3.5)
 Requirement already satisfied, skipping upgrade: google-auth in ./env/lib/python3.7/site-packages (from google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (1.11.0)
 Collecting requests-oauthlib>=0.7.0
   Downloading requests_oauthlib-1.3.0-py2.py3-none-any.whl (23 kB)
 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))': /simple/cffi/
 Collecting CFFI>=1.0
   Downloading cffi-1.14.0.tar.gz (463 kB)
      |████████████████████████████████| 463 kB 2.7 MB/s 
 Requirement already satisfied, skipping upgrade: certifi; extra == "secure" in ./env/lib/python3.7/site-packages (from urllib3[secure]<2,>=1.21; extra == "samples"->google-assistant-sdk[samples]==0.5.1) (2019.11.28)
 Requirement already satisfied, skipping upgrade: idna>=2.0.0; extra == "secure" in ./env/lib/python3.7/site-packages (from urllib3[secure]<2,>=1.21; extra == "samples"->google-assistant-sdk[samples]==0.5.1) (2.8)
 Collecting cryptography>=1.3.4; extra == "secure"
   Downloading https://www.piwheels.org/simple/cryptography/cryptography-2.8-cp37-cp37m-linux_armv7l.whl (852 kB)
      |████████████████████████████████| 852 kB 139 kB/s 
 Collecting pyOpenSSL>=0.14; extra == "secure"
   Downloading pyOpenSSL-19.1.0-py2.py3-none-any.whl (53 kB)
      |████████████████████████████████| 53 kB 38 kB/s 
 Requirement already satisfied, skipping upgrade: six>=1.9.0 in ./env/lib/python3.7/site-packages (from tenacity<5,>=4.1.0; extra == "samples"->google-assistant-sdk[samples]==0.5.1) (1.14.0)
 Collecting googleapis-common-protos>=1.5.2
   Downloading https://www.piwheels.org/simple/googleapis-common-protos/googleapis_common_protos-1.51.0-py3-none-any.whl (74 kB)
      |████████████████████████████████| 74 kB 54 kB/s 
 Collecting grpcio>=1.3.5
   Downloading grpcio-1.27.1.tar.gz (16.9 MB)
      |████████████████████████████████| 16.9 MB 28 kB/s 
 Requirement already satisfied, skipping upgrade: cachetools<5.0,>=2.0.0 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (4.0.0)
 Requirement already satisfied, skipping upgrade: setuptools>=40.3.0 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (45.2.0)
 Requirement already satisfied, skipping upgrade: rsa<4.1,>=3.1.4 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (4.0)
 Requirement already satisfied, skipping upgrade: pyasn1-modules>=0.2.1 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (0.2.8)
 Requirement already satisfied, skipping upgrade: requests>=2.0.0 in ./env/lib/python3.7/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (2.22.0)
 Collecting oauthlib>=3.0.0
   Downloading oauthlib-3.1.0-py2.py3-none-any.whl (147 kB)
      |████████████████████████████████| 147 kB 2.9 MB/s 
 Collecting pycparser
   Downloading https://www.piwheels.org/simple/pycparser/pycparser-2.19-py2.py3-none-any.whl (111 kB)
      |████████████████████████████████| 111 kB 136 kB/s 
 Collecting protobuf>=3.6.0
   Downloading protobuf-3.11.3-py2.py3-none-any.whl (434 kB)
      |████████████████████████████████| 434 kB 2.9 MB/s 
 Requirement already satisfied, skipping upgrade: pyasn1>=0.1.3 in ./env/lib/python3.7/site-packages (from rsa<4.1,>=3.1.4->google-auth->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (0.4.8)
 Requirement already satisfied, skipping upgrade: chardet<3.1.0,>=3.0.2 in ./env/lib/python3.7/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]>=0.1.0->google-assistant-sdk[samples]==0.5.1) (3.0.4)
 Building wheels for collected packages: CFFI, grpcio
   Building wheel for CFFI (setup.py) ... done
   Created wheel for CFFI: filename=cffi-1.14.0-cp37-cp37m-linux_armv7l.whl size=344199 sha256=065c9116c377d349abb73c3dab4c81e96f1f4b609feea59b0ed8e5ed7a507996
   Stored in directory: /home/pi/.cache/pip/wheels/c4/91/4f/81fe591804590e3cd010d6c54f251607dc4c61fc5eb5840a51
   Building wheel for grpcio (setup.py) ... done
   Created wheel for grpcio: filename=grpcio-1.27.1-cp37-cp37m-linux_armv7l.whl size=19730888 sha256=e82f92e8a83f098324388108730a9b139ed4e17df1ebda496b41b44af68c0a6f
   Stored in directory: /home/pi/.cache/pip/wheels/17/b1/29/54f293e4b9aa742164ebc8ba54fef15efefcca306bf6335860
 Successfully built CFFI grpcio
 Installing collected packages: oauthlib, requests-oauthlib, click, google-auth-oauthlib, pycparser, CFFI, sounddevice, tenacity, protobuf, googleapis-common-protos, grpcio, google-assistant-grpc, futures, google-assistant-sdk, cryptography, pyOpenSSL
 Successfully installed CFFI-1.14.0 click-6.7 cryptography-2.8 futures-3.1.1 google-assistant-grpc-0.2.1 google-assistant-sdk-0.5.1 google-auth-oauthlib-0.4.1 googleapis-common-protos-1.51.0 grpcio-1.27.1 oauthlib-3.1.0 protobuf-3.11.3 pyOpenSSL-19.1.0 pycparser-2.19 requests-oauthlib-1.3.0 sounddevice-0.3.14 tenacity-4.12.0
 (env) pi@raspberrypi:~ $

- google 認証ツールのインストール
 (env) pi@raspberrypi:~ $ python -m pip install --upgrade google-auth-oauthlib[tool]
 Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
 Requirement already up-to-date: google-auth-oauthlib[tool] in ./env/lib/python3.7/site-packages (0.4.1)
 Requirement already satisfied, skipping upgrade: google-auth in ./env/lib/python3.7/site-packages (from google-auth-oauthlib[tool]) (1.11.0)
 Requirement already satisfied, skipping upgrade: requests-oauthlib>=0.7.0 in ./env/lib/python3.7/site-packages (from google-auth-oauthlib[tool]) (1.3.0)
 Requirement already satisfied, skipping upgrade: click; extra == "tool" in ./env/lib/python3.7/site-packages (from google-auth-oauthlib[tool]) (6.7)
 Requirement already satisfied, skipping upgrade: rsa<4.1,>=3.1.4 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]) (4.0)
 Requirement already satisfied, skipping upgrade: setuptools>=40.3.0 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]) (45.2.0)
 Requirement already satisfied, skipping upgrade: cachetools<5.0,>=2.0.0 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]) (4.0.0)
 Requirement already satisfied, skipping upgrade: six>=1.9.0 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]) (1.14.0)
 Requirement already satisfied, skipping upgrade: pyasn1-modules>=0.2.1 in ./env/lib/python3.7/site-packages (from google-auth->google-auth-oauthlib[tool]) (0.2.8)
 Requirement already satisfied, skipping upgrade: oauthlib>=3.0.0 in ./env/lib/python3.7/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (3.1.0)
 Requirement already satisfied, skipping upgrade: requests>=2.0.0 in ./env/lib/python3.7/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (2.22.0)
 Requirement already satisfied, skipping upgrade: pyasn1>=0.1.3 in ./env/lib/python3.7/site-packages (from rsa<4.1,>=3.1.4->google-auth->google-auth-oauthlib[tool]) (0.4.8)
 Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in ./env/lib/python3.7/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (2019.11.28)
 Requirement already satisfied, skipping upgrade: idna<2.9,>=2.5 in ./env/lib/python3.7/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (2.8)
 Requirement already satisfied, skipping upgrade: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in ./env/lib/python3.7/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (1.25.8)
 Requirement already satisfied, skipping upgrade: chardet<3.1.0,>=3.0.2 in ./env/lib/python3.7/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google-auth-oauthlib[tool]) (3.0.4)

*** 認証情報の登録 [#u61ea7d4]
- 認証ツール google-oauthlib-tool コマンドを実行。&color(red){事前にgoogle cloud サイトから認証ファイル(JSONファイル)をダウンロードしておく。};
 (env) pi@raspberrypi:~ $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets client_secret_[XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX].apps.googleusercontent.com.json
 Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=1063710001909-4c3g9b9900le8dke9agqdq7i7p3c02vf.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fassistant-sdk-prototype+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgcm&state=slpK7tPNVrk7YXVk8SJJ8fxuyAAhEx&prompt=consent&access_type=offline
 Enter the authorization code: 
※「XXXXX」は実際のファイル名を入れる。

- 一旦WEBブラウザ上で上記の最後部分 https:// 以下をアクセスし、ログインしたアカウントで Googleアシスタントの使用を許可する。
- 表示された認証コードをコピーし、前記のコマンド操作の続きで「Enter the authorization code:」の後に張り付ける。
 Enter the authorization code: [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]
 credentials saved: /home/pi/.config/google-oauthlib-tool/credentials.json
 (env) pi@raspberrypi:~ $ 
- 以上で認証登録完了。

- 作成した環境にインストールされているパッケージの確認
 (env) pi@raspberrypi:~ $ pip freeze
 cachetools==4.0.0
 certifi==2019.11.28
 cffi==1.14.0
 chardet==3.0.4
 click==6.7
 cryptography==2.8
 enum34==1.1.6
 futures==3.1.1
 google-assistant-grpc==0.2.1
 google-assistant-library==1.0.1
 google-assistant-sdk==0.5.1
 google-auth==1.11.0
 google-auth-oauthlib==0.4.1
 googleapis-common-protos==1.51.0
 grpcio==1.27.1
 idna==2.8
 oauthlib==3.1.0
 pathlib2==2.3.5
 pkg-resources==0.0.0
 protobuf==3.11.3
 pyasn1==0.4.8
 pyasn1-modules==0.2.8
 pycparser==2.19
 pyOpenSSL==19.1.0
 requests==2.22.0
 requests-oauthlib==1.3.0
 rsa==4.0
 six==1.14.0
 sounddevice==0.3.14
 tenacity==4.12.0
 urllib3==1.25.8

** Google Assistant のデモ機能実行 [#afa9794b]
*** google-assistant-demo の実行 [#oaa48cbc]
- Pyson3 仮想環境をアクティベイトする。
 pi@raspberrypi:~ $ source ~/env/bin/activate
 (env) pi@raspberrypi:~ $
-「google-assistant-demo」コマンドを実行
 (env) pi@raspberrypi-mas:~ $ google-assistant-demo --project-id raspberryai-mizutu --device-model-id raspberryai-mizutu-rasaiprd-XXXXXX
 Segmentation fault
&color(red){セグメントエラーで前に進めず!!};~

>&color(red){※ 2020/02/15 記};~
- 上記で使用するコマンドは、「Googl Assistant Service」の一部である「Google Assistant Library」を使用しているらしい。~
- 「Google Assistant Library」は2019/06 で破棄されたと記述あり。今後の動作保証は望めないようだ。サイトには各種混乱状況の記述あり。
- 別途、オフィシャルサイトのドキュメントから再度検証する。~



*** 5. SDKとサンプルコードをインストールする [#s0267e9c]
-[[Install the SDK and Sample Code>+https://developers.google.com/assistant/sdk/guides/service/python/embed/install-sample]]
&color(green){ 既に完了しているので確認しながらスキップ。};

*** 6. サンプルコードを実行する [#te79cbc8]
-[[Run the Sample Code>+https://developers.google.com/assistant/sdk/guides/service/python/embed/run-sample]]~
次のコマンドを実行する。(Libraryを使わないAssistantサービスのコマンドらしい?)
 (env) pi@raspberrypi:~ $ googlesamples-assistant-pushtotalk --project-id raspberryai-mizutu --device-model-id raspberryai-mizutu-rasaiprd-bxeos5
 INFO:root:Connecting to embeddedassistant.googleapis.com
 Expression 'paInvalidSampleRate' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2048
 Expression 'PaAlsaStreamComponent_InitialConfigure( &self->capture, inParams, self->primeBuffers, hwParamsCapture, &realSr )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2719
 Expression 'PaAlsaStream_Configure( stream, inputParameters, outputParameters, sampleRate, framesPerBuffer, &inputLatency, &outputLatency, &hostBufferSizeMode )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2843
 Traceback (most recent call last):
   File "/home/pi/env/bin/googlesamples-assistant-pushtotalk", line 8, in <module>
     sys.exit(main())
   File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 722, in __call__
     return self.main(*args, **kwargs)
   File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 697, in main
     rv = self.invoke(ctx)
   File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 895, in invoke
     return ctx.invoke(self.callback, **ctx.params)
   File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 535, in invoke
     return callback(*args, **kwargs)
   File "/home/pi/env/lib/python3.7/site-packages/googlesamples/assistant/grpc/pushtotalk.py", line 351, in main
     flush_size=audio_flush_size
   File "/home/pi/env/lib/python3.7/site-packages/googlesamples/assistant/grpc/audio_helpers.py", line 190, in __init__
    blocksize=int(block_size/2),  # blocksize is in number of frames.
   File "/home/pi/env/lib/python3.7/site-packages/sounddevice.py", line 1345, in __init__
     **_remove_self(locals()))
   File "/home/pi/env/lib/python3.7/site-packages/sounddevice.py", line 861, in __init__
     'Error opening {0}'.format(self.__class__.__name__))
   File "/home/pi/env/lib/python3.7/site-packages/sounddevice.py", line 2653, in _check
     raise PortAudioError(errormsg, err)
 sounddevice.PortAudioError: Error opening RawStream: Invalid sample rate [PaErrorCode -9997]
&color(red){エラーが発生、原因と解決方法を調査。};~
&color(blue){解決のヒントをくれたサイト}; → 
[[https://github.com/googlesamples/assistant-sdk-python/issues/382]]~
次のファイルを変更する。(録音設定にレートを加える。)
 $ vi .asoundrc
 
 pcm.!default {
   type asym
   capture.pcm "mic"
   playback.pcm "speaker"
 }
 pcm.mic {
   type plug
   slave {
     pcm "hw:1,0"
     rate 48000
   }
 }
 pcm.speaker {
   type plug
   slave {
     pcm "hw:<0,0>"
   }
 }
再度コマンドを実行する。
 pi@raspberrypi:~ $ source ~/env/bin/activate
 (env) pi@raspberrypi:~ $ googlesamples-assistant-pushtotalk --project-id raspberryai-mizutu --device-model-id raspberryai-mizutu-rasaiprd-XXXXXX
 INFO:root:Connecting to embeddedassistant.googleapis.com
 WARNING:root:Device config not found: [Errno 2] No such file or directory: '/home/pi/.config/googlesamples-assistant/device_config.json'
 INFO:root:Registering device
 INFO:root:Device registered: 48b079ce-4fbf-11ea-ac12-dca63271afe7
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "who".
 INFO:root:Transcript of user request: "who are".
 INFO:root:Transcript of user request: "who I".
 INFO:root:Transcript of user request: "who  I".
 INFO:root:Transcript of user request: "who  is".
 INFO:root:Transcript of user request: "who  I".
 INFO:root:Transcript of user request: "who  is".
 INFO:root:Transcript of user request: "who  I am".
 INFO:root:Transcript of user request: "who I am".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "who I am".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "what".
 INFO:root:Transcript of user request: "what time".
 INFO:root:Transcript of user request: "what  time".
 INFO:root:Transcript of user request: "what  time is".
 INFO:root:Transcript of user request: "what time  is".
 INFO:root:Transcript of user request: "what time  is it".
 INFO:root:Transcript of user request: "what time is  it".
 INFO:root:Transcript of user request: "what time is it".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "what time is it".
 INFO:root:Playing assistant response.
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "what".
 INFO:root:Transcript of user request: "what  is".
 INFO:root:Transcript of user request: "what  is a".
 INFO:root:Transcript of user request: "what  is".
 INFO:root:Transcript of user request: "what is".
 INFO:root:Transcript of user request: "what is  a".
 INFO:root:Transcript of user request: "what is  the".
 INFO:root:Transcript of user request: "what is  this".
 INFO:root:Transcript of user request: "what is this".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "what is this".
 INFO:root:Playing assistant response.
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "what".
 INFO:root:Transcript of user request: "what is".
 INFO:root:Transcript of user request: "what  is".
 INFO:root:Transcript of user request: "what is".
 INFO:root:Transcript of user request: "what is  the".
 INFO:root:Transcript of user request: "what is the".
 INFO:root:Transcript of user request: "what is The  Wiz".
 INFO:root:Transcript of user request: "what is the  least".
 INFO:root:Transcript of user request: "what is the  reason".
 INFO:root:Transcript of user request: "what is the  weasel".
 INFO:root:Transcript of user request: "what is the  wizard".
 INFO:root:Transcript of user request: "what is the  result".
 INFO:root:Transcript of user request: "what is the result".
 INFO:root:Transcript of user request: "what is the result  in".
 INFO:root:Transcript of user request: "what is the result  in some".
 INFO:root:Transcript of user request: "what is the result  in South".
 INFO:root:Transcript of user request: "what is the result in  South".
 INFO:root:Transcript of user request: "what is the result in  San".
 INFO:root:Transcript of user request: "what is the result in  San Fran".
 INFO:root:Transcript of user request: "what is the result in  San".
 INFO:root:Transcript of user request: "what is the result in  San Francisco".
 INFO:root:Transcript of user request: "what is the result in San  Francisco".
 INFO:root:Transcript of user request: "what is the  weather in San Francisco".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "what is the weather in San Francisco".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 ^C
 Aborted!
 Segmentation fault
&color(green){一応スペースキーで英語の音声入力を受け付けて、応答するようになった。};~

>冒頭に出る WARNING: については、ドキュメント「初回にデバイスインスタンスIDを見つける」の項目によれば~

--サンプルを初めて実行すると、特定のデバイスのデバイスインスタンスが生成され、モデルIDとインスタンスIDの両方が保存される。これらを引数として指定せずにサンプルを実行すると、デフォルトでは保存されたIDが使用される。~
--上記では、デバイスインスタンスID → 48b079ce-4fbf-11ea-ac12-dca63271afe7

*** 6-1. Google Assistant を日本語化する [#mde3c089]
-スマートフォンに「Google Assistant」アプリをインストールする。~
-書籍の手順とは若干の変更があるようだが、スマートフォンのアプリから「アシスタントの言語」設定で、「日本語(日本)」を追加して選択する。
-もう一度 6. のコマンドを入力する。プロジェクトIDなどは初回の設定情報が保存されているので必要なし。
-起動後、スペースキーを押して「今日の天気を教えて」「今日は何の日」など質問してみる。
 pi@raspberrypi:~ $ source ~/env/bin/activate
 (env) pi@raspberrypi:~ $ googlesamples-assistant-pushtotalk
 INFO:root:Connecting to embeddedassistant.googleapis.com
 INFO:root:Using device model raspberryai-mizutu-rasaiprd-bxeos5 and device id 48b079ce-4fbf-11ea-ac12-dca63271afe7
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "turn".
 INFO:root:Transcript of user request: "turn off".
 INFO:root:Transcript of user request: "turn off thank".
 INFO:root:Transcript of user request: "turn off thank you".
 INFO:root:Transcript of user request: "turn off thank you so".
 INFO:root:Transcript of user request: "turn off thank you say".
 INFO:root:Transcript of user request: "turn off thank you Siri".
 INFO:root:Transcript of user request: "turn off thank  you set".
 INFO:root:Transcript of user request: "turn off thank  you Siri".
 INFO:root:Transcript of user request: "turn off thank  you set".
 INFO:root:Transcript of user request: "turn off thank you  Seattle".
 INFO:root:Transcript of user request: "turn off thank you  say that".
 INFO:root:Transcript of user request: "turn off thank you  set it".
 INFO:root:Transcript of user request: "turn off thank you  say that".
 INFO:root:Transcript of user request: "turn off thank you say that".
 INFO:root:Transcript of user request: "今日".
 INFO:root:Transcript of user request: "今日の".
 INFO:root:Transcript of user request: "今日のて".
 INFO:root:Transcript of user request: "今日の天気".
 INFO:root:Transcript of user request: "今日の天気を".
 INFO:root:Transcript of user request: "今日の天気をお".
 INFO:root:Transcript of user request: "今日の天気を教え".
 INFO:root:Transcript of user request: "今日の天気を教えて".
 INFO:root:Transcript of user request: "今日の天気を教えて".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今日の天気を教えて".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "kill".
 INFO:root:Transcript of user request: "kill the".
 INFO:root:Transcript of user request: "kilwin and no heat".
 INFO:root:Transcript of user request: "今日".
 INFO:root:Transcript of user request: "今日は".
 INFO:root:Transcript of user request: "今日は 何".
 INFO:root:Transcript of user request: "今日は何の".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 INFO:root:Finished playing assistant response.
 Press Enter to send a new request...
 INFO:root:Recording audio request.
 ^C
 Aborted!
&color(green){スペースキーで日本語の音声入力を受け付けて、応答するようになった。};~
-動画 (96.6MB 38秒) &ref(http://izutsu.aa0.netvolante.jp/video/20200216_104826_001.mp4, スマートスピーカーの応答の様子);

** スマートスピーカーのカスタマイズ [#labd29dd]
#ref(画像一覧/fig4-2.jpg,right,around,25%,fig4-2.jpg)
#ref(画像一覧/fig4-1.jpg,right,around,25%,fig4-1.jpg)
> ハードウェアボタン(タクトSW)とLEDを紐づけて、ボタンを押して「Push to Talk」を起動させるようにする。~
LEDタクトSWの接続回路は右記のとおり。

- gitコマンドで Google Assistant のサンプルデータをローカル環境に移す。
 $ git clone https://github.com/googlesamples/assistant-sdk-python.git
 Cloning into 'assistant-sdk-python'...
 remote: Enumerating objects: 19, done.
 remote: Counting objects: 100% (19/19), done.
 remote: Compressing objects: 100% (17/17), done.
 remote: Total 2057 (delta 6), reused 7 (delta 2), pack-reused 2038
 Receiving objects: 100% (2057/2057), 677.72 KiB | 961.00 KiB/s, done.
 Resolving deltas: 100% (1142/1142), done.
 $ ls
 Desktop  Documents  Downloads  MagPi  Music  Pictures  Programs  Public  Templates  Videos  assistant-sdk-python  env  out.raw
ホームディレクトリ内に「assistant-sdk-python」ディレクトリができる。
#clear

-「Programs」ディレクトリ内に必要なデータをコピーする。
 $ mkdir ~/Programs/googlesamples
 $ ls Programs
 --device-model-id  googlesamples  hello.py  hello_nihongo.py  hello_today.py  image  key.txt  led.py  sound  switch_led.py  switch_speaker.py  xmodmap.txt
 
 $ cd ~/assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/
 $ cp -r grpc ~/Programs/googlesamples
 
 $ cd ~/Programs/googlesamples/grpc/
 $ ls
 README.rst   assistant_helpers.py  audiofileinput.py   device_helpers.py  pushtotalk.py     textinput.py
 __init__.py  audio_helpers.py      browser_helpers.py  devicetool.py      requirements.txt
以下、前の候の続き。

*** 7. Button To Talk プログラムの作成 [#l899c0ec]
-サンプルプログラム内の「pushtotalk.py」を「buttontotalk.py」という名前で複製する。
 $ cp pushtotalk.py buttontotalk.py
 $ ls
 README.rst   assistant_helpers.py  audiofileinput.py   buttontotalk.py    devicetool.py  requirements.txt
 __init__.py  audio_helpers.py      browser_helpers.py  device_helpers.py  pushtotalk.py  textinput.py

-「buttontotalk.py」ファイルを編集する。
1行目に追加
 # _*_ coding: utf-8 _*_
25行目付近に定義の追加
 import time
 import uuid
 
 import click
 import grpc
 import google.auth.transport.grpc
 import google.auth.transport.requests
 import google.oauth2.credentials
 
 """ 2020/02/17 mizutu """
 import RPi.GPIO as GPIO
 LED = 16
 BUTTON = 20
320行付近にGPIOセットアップ追加
    """Samples for the Google Assistant API.
 
    Examples:
      Run the sample with microphone input and speaker output:
 
        $ python -m googlesamples.assistant
 
      Run the sample with file input and speaker output:
 
        $ python -m googlesamples.assistant -i <input file>
 
      Run the sample with file input and output:
 
        $ python -m googlesamples.assistant -i <input file> -o <output file>
    """
 
    """ 2020/02/17 mizutu """
    GPIO.setmode(GPIO.BCN)
    GPIO.setwarnings(False)
    GPIO.setup(BUTTON, GPIO.IN)
    GPIO.setup(LED, GPIO.OUT, initial=GPIO.LOW)
    GPIO.add_event_detect(BUTTON,GPIO.FALLING)
 
    # Setup logging.
450行付近にボタンが押されたときのイベント追加
        wait_for_user_trigger = not once
        while True:
            if wait_for_user_trigger:
 
              """ 2020/02/17 mizutu """
              # Add button function
              # click.pause(info='Press Enter to send a new request...')
              logging.info("ボタンを押して話しかけてください!")
              if GPIO.event_detected(BUTTON):
                  GPIO.output(LED, GPIO.HIGH)
                  pass
              else:
                  GPIO.output(LED, GPIO.HIGH)
                  time.sleep(0.5)
                  GPIO.output(LED, GPIO.LOW)
                  time.sleep(0.5)
                  continue
 
            continue_conversation = assistant.assist()
            # wait for user trigger if there is no follow-up turn in
            # the conversation.

-「buttontotalk.py」プログラムを実行する。
 $ source ~/env/bin/activate
 (env) $ python buttontotalk.py
 Traceback (most recent call last):
   File "buttontotalk.py", line 36, in <module>
     import RPi.GPIO as GPIO
 ModuleNotFoundError: No module named 'RPi'
&color(red){RPiモジュールがないとエラー発生};
前に作った led.py プログラムを実行してみる。
 (env) $ cd ~/Programs
 (env) pi@raspberrypi-mas:~/Programs $ python led.py
   File "led.py", line 13
     print "LED ON!"
                   ^
 SyntaxError: Missing parentheses in call to 'print'. Did you mean print("LED ON!")?
&color(red){python3 ではprint文のフォーマットが違うとエラー};
vi で print('xxxx')に変更して実行してみる。
 (env) pi@raspberrypi-mas:~/Programs $ python led.py3
 Traceback (most recent call last):
   File "led.py3", line 4, in <module>
     import RPi.GPIO as GPIO
 ModuleNotFoundError: No module named 'RPi'
&color(red){同じくRPiモジュールがないとエラー発生};

- 仮想環境のモジュールを調べる。
 (env) $ pip3 list
 Package                  Version   
 ------------------------ ----------
 cachetools               4.0.0     
 certifi                  2019.11.28
 cffi                     1.14.0    
 chardet                  3.0.4     
 click                    6.7       
 cryptography             2.8       
 enum34                   1.1.6     
 futures                  3.1.1     
 google-assistant-grpc    0.2.1     
 google-assistant-library 1.0.1     
 google-assistant-sdk     0.5.1     
 google-auth              1.11.0    
 google-auth-oauthlib     0.4.1     
 googleapis-common-protos 1.51.0    
 grpcio                   1.27.1    
 idna                     2.8       
 oauthlib                 3.1.0     
 pathlib2                 2.3.5     
 pip                      20.0.2    
 pkg-resources            0.0.0     
 protobuf                 3.11.3    
 pyasn1                   0.4.8     
 pyasn1-modules           0.2.8     
 pycparser                2.19      
 pyOpenSSL                19.1.0    
 requests                 2.22.0    
 requests-oauthlib        1.3.0     
 rsa                      4.0       
 setuptools               45.2.0    
 six                      1.14.0    
 sounddevice              0.3.14    
 tenacity                 4.12.0    
 urllib3                  1.25.8    
 wheel                    0.34.2    

- 仮想環境に RPi.GPIO モジュールをインストールする。
 (env) $  pip install RPi.GPIO
 Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
 Collecting RPi.GPIO
   Downloading https://www.piwheels.org/simple/rpi-gpio/RPi.GPIO-0.7.0-cp37-cp37m-linux_armv7l.whl (69 kB)
      |████████████████████████████████| 69 kB 64 kB/s
 Installing collected packages: RPi.GPIO
 Successfully installed RPi.GPIO-0.7.0
インストールを確認する。
 (env) $ pip list
 Package                  Version   
 ------------------------ ----------
 cachetools               4.0.0     
 certifi                  2019.11.28
 cffi                     1.14.0    
 chardet                  3.0.4     
 click                    6.7       
 cryptography             2.8       
 enum34                   1.1.6     
 futures                  3.1.1     
 google-assistant-grpc    0.2.1     
 google-assistant-library 1.0.1     
 google-assistant-sdk     0.5.1     
 google-auth              1.11.0    
 google-auth-oauthlib     0.4.1     
 googleapis-common-protos 1.51.0    
 grpcio                   1.27.1    
 idna                     2.8       
 oauthlib                 3.1.0     
 pathlib2                 2.3.5     
 pip                      20.0.2    
 pkg-resources            0.0.0     
 protobuf                 3.11.3    
 pyasn1                   0.4.8     
 pyasn1-modules           0.2.8     
 pycparser                2.19      
 pyOpenSSL                19.1.0    
 requests                 2.22.0    
 requests-oauthlib        1.3.0     
 RPi.GPIO                 0.7.0     
 rsa                      4.0       
 setuptools               45.2.0    
 six                      1.14.0    
 sounddevice              0.3.14    
 tenacity                 4.12.0    
 urllib3                  1.25.8    
 wheel                    0.34.2    

- テストプログラムを実行してみる。
 (env) $ python led.py3
 led.py3:8: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
   GPIO.setup(LED, GPIO.OUT)
 LED ON!
 LED ON!
 LED ON!

- 問題が解消したようなので、buttontotalk.py プログラムを実行する。
 (env) $ python buttontotalk.py
 INFO:root:Connecting to embeddedassistant.googleapis.com
 INFO:root:Using device model raspberryai-mizutu-rasaiprd-bxeos5 and device id 48b079ce-4fbf-11ea-ac12-dca63271afe7
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "kill".
 INFO:root:Transcript of user request: "kiln".
 INFO:root:Transcript of user request: "kill nothing".
 INFO:root:Transcript of user request: "kill no thank".
 INFO:root:Transcript of user request: "kill no thank you".
 INFO:root:Transcript of user request: "kill no thank you are".
 INFO:root:Transcript of user request: "kill  no thank you are".
 INFO:root:Transcript of user request: "kill  no thank you up".
 INFO:root:Transcript of user request: "kill no thank  you up".
 INFO:root:Transcript of user request: "kill no thank you  up".
 INFO:root:Transcript of user request: "今日".
 INFO:root:Transcript of user request: "今日の".
 INFO:root:Transcript of user request: "今日のて".
 INFO:root:Transcript of user request: "今日の天気".
 INFO:root:Transcript of user request: "今日の天気は".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今日の天気は".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 WARNING:root:SoundDeviceStream write underflow (size: 4000)
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "kill".
 INFO:root:Transcript of user request: "cool".
 INFO:root:Transcript of user request: "kilwin under Heat".
 INFO:root:Transcript of user request: "今日".
 INFO:root:Transcript of user request: "今日は".
 INFO:root:Transcript of user request: "今日は 何".
 INFO:root:Transcript of user request: "今日は何の".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 ^Z
 [7]+  停止                  python buttontotalk.py
&color(green){キーボードの代わりにタクトSWで音声入力できるようになった。};

-&color(red){2回目実行するとエラーとなることが判明。reboot すると1回目だけ正常、2回目以降エラー発生で止まる。};~
悩んだ結果、プログラムの終了を「Ctrl+z」を押したのが間違いのようだ。(上記 停止で終わっている)
 (env) $ python buttontotalk.py
 INFO:root:Connecting to embeddedassistant.googleapis.com
 INFO:root:Using device model raspberryai-mizutu-rasaiprd-bxeos5 and device id 48b079ce-4fbf-11ea-ac12-dca63271afe7
 INFO:root:ボタンを押して話しかけてください!
            :
 INFO:root:ボタンを押して話しかけてください!
 ^C
 Aborted!
&color(red){「Ctrl+c」で終了すると問題が解消した。(^_^;)};
''「Ctrl+D」で停止したプログラムは以下のコマンドで再スタートことがわかる。''
 $ fg
-「buttontotalk.py」の最後にGPIO の初期化コマンドを追加。
             # If we only want one conversation, break.
             if once and (not continue_conversation):
                 break
 
     """ 2020/02/17 mizutu """
     GPIO.cleanup()
 
 if __name__ == '__main__':
     main()

** 7-1. 独自コマンド Traits 追加 [#z363a2b5]
- Google の用意した特定の音声コマンドをハードウェアに紐づけする機能を利用する。~
「buttontotalk.py」を「buttontotalk_traits.py」として複製する。
 $ cp buttontotalk.py buttontotalk_traits.py
「Turn On」でLEDが素早く点滅し、「Turn Off」でLEDが消えるようにカスタマイズ。
「buttontotalk_traits.py」に下記の変更を加える。
                   :
    @device_handler.command('action.devices.commands.OnOff')
    def onoff(on):
        if on:
            logging.info('Turning device on')
 
            """ 2020/02/17 miautu """
            for i in range(5):
                GPIO.output(LED, GPIO.HIGH)
                time.sleep(0.2)
                GPIO.output(LED, GPIO.LOW)
                time.sleep(0.2)
        else:
            logging.info('Turning device off')
 
            """ 2020/02/17 miautu """
            GPIO.output(LED.GPIO, LOW)
 
    @device_handler.command('com.example.commands.BlinkLight')
                    :
- python3 環境で「buttontotalk_traits.py」を実行してみる。
 $ source ~/env/bin/activate
 (env) $ python buttontotalk_traits.py
 INFO:root:Connecting to embeddedassistant.googleapis.com
 INFO:root:Using device model raspberryai-mizutu-rasaiprd-bxeos5 and device id 48b079ce-4fbf-11ea-ac12-dca63271afe7
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "今日".
 INFO:root:Transcript of user request: "今日は".
 INFO:root:Transcript of user request: "今日は 何".
 INFO:root:Transcript of user request: "今日は何の".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今日は何の日".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "talk".
 INFO:root:Transcript of user request: "Tom".
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Transcript of user request: "turn on".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Playing assistant response.
 WARNING:root:SoundDeviceStream write underflow (size: 1600)
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 ^C
 Aborted!
''「Turn On」は認識しているようだが、反応はしていない模様。(引き続き調査)''

** WARNING:root:SoundDeviceStream write underflow について [#mad55fd1]
- Google Assistant サービス利用中に出る WORNING エラーを調査。
ドキュメントに「--audio-block-size」を調整しろとあるのでやってみる。
 (env) $ python -m audio_helpers --audio-block-size=3200
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 WARNING:root:SoundDeviceStream write underflow (size: 6400)
           :
 WARNING:root:SoundDeviceStream write underflow (size: 6400)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
 (env) $ python -m audio_helpers --audio-block-size=80000
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
 (env) $ python -m audio_helpers --audio-block-size=8000
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
 (env) $ python -m audio_helpers --audio-block-size=0
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 ^C
 Aborted!
 (env) $ python -m audio_helpers --audio-block-size=6400
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 WARNING:root:SoundDeviceStream write underflow (size: 12800)
 WARNING:root:SoundDeviceStream write underflow (size: 12800)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
 (env) $ python -m audio_helpers --audio-block-size=8000
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
 (env) $ python -m audio_helpers --audio-block-size=8000
 INFO:root:Starting audio test.
 INFO:root:Recording samples.
 INFO:root:Finished recording.
 INFO:root:Playing back samples.
 /home/pi/Programs/googlesamples/grpc/audio_helpers.py:326: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
   buf = normalize_audio_buffer(buf, self.volume_percentage)
 WARNING:root:SoundDeviceStream write underflow (size: 16000)
 INFO:root:Finished playback.
 INFO:root:audio test completed.
エラーの出ないのは「--audio-block-size=80000」なので、これで実行してみる。
 (env) $ python -m buttontotalk_traits --audio-block-size=80000
 INFO:root:Connecting to embeddedassistant.googleapis.com
 INFO:root:Using device model raspberryai-mizutu-rasaiprd-bxeos5 and device id 48b079ce-4fbf-11ea-ac12-dca63271afe7
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Transcript of user request: "turn on".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Playing assistant response.
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "turn".
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Transcript of user request: "turn  on".
 INFO:root:Transcript of user request: "turn on".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "turn on".
 INFO:root:Playing assistant response.
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:Recording audio request.
 INFO:root:Transcript of user request: "今".
 INFO:root:Transcript of user request: "今何".
 INFO:root:Transcript of user request: "今何時".
 INFO:root:Transcript of user request: "今何時".
 INFO:root:Transcript of user request: "今何時".
 INFO:root:End of audio request detected.
 INFO:root:Stopping recording.
 INFO:root:Transcript of user request: "今何時".
 INFO:root:Playing assistant response.
 INFO:root:Finished playing assistant response.
 INFO:root:ボタンを押して話しかけてください!
 INFO:root:ボタンを押して話しかけてください!
 ^C
 Aborted!
- WORNING エラーは出なくなるが反応が遅くなる。
- 音声応答が長い場合、途中で終了してしまう場合がある。
-「Turn On」の音声に対する反応は変わらず。~

>''7-1. 項の問題とは無関係と結論。--audio-block-size はデフォールトのままとする。''

> 参考サイト:[[Python SoundDeviceStream write/read underflow/overflow errors>+https://stackoverflow.com/questions/53224787/python-sounddevicestream-write-read-underflow-overflow-errors]]
#br