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で実装

下記を参考に

【AWS Lambdaの基本コードその4】 AWS IoTにメッセージをPublish

事前に作っておいたエンドポイント 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ファイルを再生

音声ファイルの生成処理は下記を参照

AWS SDK for Python (boto3)でAmazon Pollyの声を使い分けてみる

 

mp3の再生は下記を参考に

第12回「Raspberry Piで音遊び!」

 

コマンドラインからの再生テスト

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