root, 非rootwを意識する必要がある
http://www.yunabe.jp/docs/python_package_management.html
# pip install paho-mqtt
-> /usr/local/lib/python2.7/dist-packages/paho
パスに権限がない場合
$ pip install paho-mqtt
-> /home/pi/.local/lib/python2.7/site-packages/paho
パスの違いに注意
root, 非rootwを意識する必要がある
http://www.yunabe.jp/docs/python_package_management.html
# pip install paho-mqtt
-> /usr/local/lib/python2.7/dist-packages/paho
パスに権限がない場合
$ pip install paho-mqtt
-> /home/pi/.local/lib/python2.7/site-packages/paho
パスの違いに注意
slackのOutgoing Webhooksから受信する
Proxy統合ではなく、Lambda側のインタフェースを決めてしまう
/raspberrypi/{proxy+} を作成し、POSTのみ作成
/raspberrypi/speak で呼び出し、speakの場合、音声再生要求を投げる
Lambda関数を作成
実装はシンプル
https://github.com/nilesflow/Slack2RaspberryPi
下記等参考に
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
query paramaterのtokenの値の検証のみ
tokenの値はコンソール上の環境変数に設定
Lambdaを登録しておく。
フォーマットは下記の形式
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
Lambdaオーソライザー
ロールはLambda実行権限含むものを作成しておく
クエリパラメータにtokenを設定して認証させたいので、認証でLambdaリクエストオーソライザーを設定。
~検証とURLクエリ文字列パラメータを設定。
リクエストパスのproxyを入力しておく
・作成したLambdaを指定
・プロキシ統合は使わずに、呼び出し側ロジックはAPI Gateway側で吸収
・リクエストパラメータのproxyをマッピング
・Content-Type=application/x-www-form-urlencoded で送信される
・それ以外は厳しめに通過禁止に設定しておく
・マッピングテンプレートは次の通り
## slackのOutgoing Webhooksから下記の形式で送信される
## token=viK8ruCmEfBjd9u84MOEeTWo
## team_id=T0001
## team_domain=例
## channel_id=C2147483705
## channel_name=テスト
## timestamp=1355517523.000005
## user_id=U2147483697
## user_name=スティーブ
## text=googlebot: 身軽なツバメの対気速度はどのくらい?
## trigger_word=googlebot:## POSTパラメータの分割(A=x&B=y)
#set($aParams = $input.body.split(“&”))## path変数の分割
#set($aPaths = $input.params(‘proxy’).split(“/”))## 出力されるJSONデータの生成
{
##pathの次階層をactionとする
“action” : “$aPaths[0]”,## 必要なPOSTパラメータのみをマッピング
#foreach( $param in $aParams)
#set($hParam = $param.split(“=”))
#if( $hParam[0] == “text”)
“text” : “$util.urlDecode($hParam[1])”,
#end
#if( $hParam[0] == “user_name”)
“user” : “$util.urlDecode($hParam[1])”,
#end
#end## カンマ制御のためのダミー
“dummy” : null
}
Lambda側で定義される次の変数をマッピングしている
action
text
user
・統合レスポンスは200のみ設定
slackへ応答を返すには、200でレスポンスパラメータを返す必要があるため
マッピングテンプレートは次の通り
## for slack Outgoing Webhooks
## 全て200の単一フォーマットで返却
#set ($inputRoot = $input.path(‘$’))## Lambdaで正常に処理された場合
#if ($input.path(‘$.statusCode’) > 0)## 200の場合のフォーマット
#if ($input.path(‘$.statusCode’) == 200)
#set ($body = $util.parseJson($input.path(‘$.body’)))
{
“text” : “$body.message”
}## それ以外の場合のフォーマット
#else ## 200
#set ($body = $util.parseJson($input.path(‘$.body’)))
{
“text” : “$body.error: $body.error_description”
}
#end ## not 200## 例外等
#else ## statusCode
{
“text” : “$input.path(‘$.errorMessage’)”
}
#end ## not statusCode
Lambdaの応答の次のケース全てを200として返却する
・ステータスコード200:正常
・ステータスコード200以外:異常(Lambda実装コード中で認識したエラー)
・例外等それ以外:異常(Lambda実装コード中以外のエラーも含む)
・ゲートウェイのレスポンスで、API Gatewayで検出したエラーのレスポンスフォーマットを定義する
これも、SlackのOutgoing Webhooksのフォーマットに合わせておく。
400, 500も200で返すようにしておく。
メソッドレスポンスモデルは不要なのか。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-method-settings-method-response.html
統合レスポンス、ゲートウェイのレスポンスでまかなえているようだった。
slack → RaspberryPiを実現するため
python3.6で実装
下記を参考に
事前に作っておいたエンドポイント raspberrypi/speak へ送信
RaspberryPi側でsubscribeできることを確認しておく
Lambda応答
return {
‘isBase64Encoded’: False,
‘statusCode’: statusCode,
‘body’: json.dumps(dict),
‘headers’: {
‘Content-Type’: ‘application/json’,
},
}
Lambdaの注意点
API Gateway側でプロキシ統合を選んだ場合は、Lambda側で実装しなくてはならない
API Gateway側で吸収するなら、決まった形式で返す必要がある
こことか参考にさせてもらった
https://qiita.com/taknuki/items/dd47d1c6d4190b52df9a#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9
テスト送信しておく
AWS IoT
raspberry pi用のthingsを作成
ダウンロードした証明書とroot証明書を配置、エンドポイントを控えておく
Raspberry Pi
AWS IoTのMQTTクライアントを導入。Pahoを使用。
下記にまとめている
https://github.com/nilesflow/AWSIoTSpeaker/blob/master/README.md
AWS IoT Device SDK for C 等もあるが、pythonクライアントとした
下記ソースを参考にさせて貰った
MQTT with AWS IoT Platform using Python and Paho
から参照して下記Git Repository
https://github.com/pradeesi/AWS-IoT-with-Python-Paho
準備
pip install paho-mqtt
pip install boto3
git clone https://github.com/nilesflow/AWSIoTSpeaker/blob/master/README.md
証明書を配置
vi config.ini
- AWS IoTのHost、証明書情報を入力
- トピック名を指定
今回は、raspberrypi/#とした
起動(バックグラウンド起動しておく)
python index.py &
Amazon polly でテキスト→音声変換し、mp3ファイルをローカルに保存
mp3ファイルを再生
音声ファイルの生成処理は下記を参照
mp3の再生は下記を参考に
コマンドラインからの再生テスト
apt-get install mpg321
mpg321 polly.mp3
pythonからの再生は下記を参照
https://qiita.com/Nyanpy/items/cb4ea8dc4dc01fe56918
pygameで再生
上記ソースでは、raspberrypi/speak トピックで指定音声を再生するようにしている
AWS IoTのテスト画面からトピックを発行して確認しておく
HW: Raspberry pi model B+
Raspbian GNU/Linux 9.1 (stretch)
下記記事を参考に
http://d.hatena.ne.jp/embedded/20151025/p1
インストール
$ sudo apt-get install ipheth-utils libimobiledevice-utils ifuse usbmuxd
$ sudo mkdir /media/iphone$ sudo ifuse /media/iphone
認識しなかったので、USBを抜き差し
iPhoneで信頼するデバイスかどうかの確認が表示される
信頼すると、USBテザリングが繋がる
HW: Raspberry pi model B+
Raspbian GNU/Linux 9.1 (stretch)
バージョンの確認
https://qiita.com/fujit33/items/16ce964c228a63a9d8dd
音の確認は下記を参考に。
https://qiita.com/plsplsme/items/57b8d79d3725497fd69b
※そのままの設定で全部鳴った
ノイズ対策
そのままだと気になるくらいバックグラウンドノイズが酷い。
下記記事中のファームアップデートとコンフィグ設定で殆ど気にならないくらいまで改善。
ファームの更新
$ sudo rpi-update
コンフィグ設定
vi /boot/config.txt
12345 disable_pvt=1force_turbo=1audio_pwm_mode=2audio_sdm_mod_order=2再起動
123 $ sudo shutdown <span class="synSpecial">-r</span> now下記実行
1 $ amixer cset <span class="synIdentifier">numid</span>=<span class="synConstant">3</span> <span class="synConstant">1</span>