Certificate ManagerでSSL証明書取得
※DNSでもメールでもどちらでも
メールの方が少し早い
先ほど作った証明書を選択、「API」を選択
Route 53で、ターゲットドメインのALIASでドメインを作成
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>
HTTP1.1
RFC 7231
https://triple-underscore.github.io/RFC7231-ja.html
https://triple-underscore.github.io/RFC7231-ja.html#section-5.3.5
1 |
<dfn id="p.Accept-Language"><code class="production">Accept-Language</code></dfn> = 1#( <a href="https://triple-underscore.github.io/RFC7231-ja.html#p.language-range"><code class="production">language-range</code></a> [ <a href="https://triple-underscore.github.io/RFC7231-ja.html#p.weight"><code class="production">weight</code></a> ] ) <dfn id="p.language-range"><code class="production">language-range</code></dfn> = <language-range, <a href="http://tools.ietf.org/html/rfc4647#section-2.1">RFC 4647, 2.1 節</a>> |
↓
RFC 4647
言語タグの照合
“言語範囲” (“language-range”) の構文定義
言語範囲と言語タグ (language tags) を比較し照合するためのメカニズム
September 2006
http://ofmind.net/doc/rfc/ja/4647#SEC2.1
言語タグと言語範囲は大文字小文字を区別して扱われるべきではない: いくつかのサブタグを大文字にする慣習が存在するが,それが何か意味を持ってはならない。 言語タグと言語範囲との照合は大文字小文字を区別しないやり方で行われなければならない。
language-range = (1*8ALPHA *(“-” 1*8alphanum)) / “*”
alphanum = ALPHA / DIGIT
ALPHA
= %x41-5A / %x61-7A
; 英字( A-Z / a-z )
↓
言語タグに類似している
RFC4646
http://pentan.info/doc/rfc/j4646.html
region = 2ALPHA ; ISO 3166 code
/ 3DIGIT ; UN M.49 code
私用と拡大を含むタグとそれらの「副-タグ」は大文字と小文字を区別しないとして扱われることになっています: いくらかの「副-タグ」の資源化のためのコンベンションは存在しますが、意味を運ぶためにこれらを取ってはいけません。
o [ISO3166-1] recommends that country codes be capitalized (‘MN’
Mongolia).
o [ISO3166-1]は、国名略号が大文字で書かれることを(‘ミネソタ’モンゴル)勧めます。
“基本言語範囲” (basic language range) は [RFC3066] の言語タグと同じ構文である。
↓
https://www.ietf.org/rfc/rfc3066.txt
2.1 Language tag syntax
The language tag is composed of one or more parts: A primary language
subtag and a (possibly empty) series of subsequent subtags.
The syntax of this tag in ABNF [RFC 2234] is:
Language-Tag = Primary-subtag *( “-” Subtag )
Primary-subtag = 1*8ALPHA
Subtag = 1*8(ALPHA / DIGIT)
The productions ALPHA and DIGIT are imported from RFC 2234; they
denote respectively the characters A to Z in upper or lower case and
the digits from 0 to 9. The character “-” is HYPHEN-MINUS (ABNF:
%x2D).
All tags are to be treated as case insensitive; there exist
conventions for capitalization of some of them, but these should not
be taken to carry meaning. For instance, [ISO 3166] recommends that
country codes are capitalized (MN Mongolia), while [ISO 639]
recommends that language codes are written in lower case (mn
Mongolian).
– All 2-letter subtags are interpreted as ISO 3166 alpha-2 country
codes from [ISO 3166], or subsequently assigned by the ISO 3166
maintenance agency or governing standardization bodies, denoting
the area to which this language variant relates.
# nodeの準備
cd /usr/local/src
wget https://nodejs.org/dist/v6.11.2/node-v6.11.2-linux-x64.tar.xz
xz -dc node-v6.11.2-linux-x64.tar.xz | tar xfv –
cp node-v6.11.2-linux-x64/bin/node /usr/local/bin/node-stable
# npm の準備
#npm が存在する環境の場合、そのnpmで良いか確認。
#npm が無い環境の場合、npmをdownload。★環境のnpmが上書きされるので注意
curl -L https://www.npmjs.com/install.sh | sh
#必要に応じてバージョン指定
curl -L https://www.npmjs.com/install.sh | env npm_install=2.11.3 sh
#i18next-conv , i18next-scanner の場合
# インストール
npm -g install i18next-conv
# -> /usr/local/bin/i18next-conv -> ../lib/node_modules/i18next-conv/bin/index.js
npm -g install i18next-scanner
# -> /usr/local/lib/node_modules/i18next-scanner/
# 実行
/usr/local/bin/node-stable /usr/local/bin/i18next-conv -h
export NODE_PATH=$(npm root -g) && /usr/local/bin/node-stable index.js
# -> include “var Parser = Parser;”
i18next.use(i18nextXHRBackend).init({
lng: ‘ja’,
fallbackLng: ‘ja’,
該当言語で見つからなかったら、デフォルト言語表示できる。
jsonの中身が、null か、””で。
potファイル生成
xgettext hello.php –from-code UTF-8 –add-comments=TRANSLATORS –output=default.pot
poファイル生成
msginit –locale=ja –input=default.pot
poファイル生成
msgmerge –no-fuzzy-matching ja.po default.pot -o ja.new.po
msgmerge –no-fuzzy-matching ja.po default.pot -o ja.new.po –sort-by-file
と同じ。
msgmerge –no-fuzzy-matching ja.po default.pot -o ja.new.po –sort-output
は不要。poeditでもソート可。未翻訳テキストソートも。