Amazon Polly に駅すぱあとの検索結果を話してもらう #aws #jawsug #駅すぱあと #ヴァル研究所
★この記事は「ヴァル研究所 Advent Calendar 2016」の23日分のエントリーになります
注意
- 機能/サービスの検証とスクリーンショットの取得は
2016/12/18
に行いました。 - それ以降に変更が加えられた場合は結果が異なる可能性がありますのでご注意下さい。
- 検証時に利用可能なサービスで検証しています。実際にご利用になる前に確認していただくようお願いします。
はじまり
今年は↓のように今所属している会社のアドベントカレンダーに参加してみました。
その際に企業・学校・団体単位のアドベントカレンダーがこんなに沢山あるのを知りました。
その中で見たことある会社のがあるっ!これはっ!となり、中の人に
- 私「こんなの始めたんですね!」
- 中の人「スタートしたんですが、あんまり書く人がいないっぽいです」
- 私「おーそれは残念ですね」
社内にアドベントカレンダーの楽しさみたいなのが浸透するにはまだまだ時間がかかりそうな感じですね・・・
日本における技術系アドベントカレンダーの歴史 - 近&況
http://yhara.jp/2016/12/01/history-adcal-jp
re:Inventに参加した人とか、報告会を開催したとかでも良いので参加してみたらいいのになぁー残念。
もしくは去年の今頃のように、まだ勇者になってない頃に訪問してもらい桃鉄
やってもらうのでも十分ネタになりそうですがw
先日新作も出たみたいですし、もう一度勇者の姿で訪問して桃鉄でもやったらいいんじゃないですかねぇ?w
せっかくだから
せっかくだから、俺はこの赤の扉を選ぶぜ!
ではなくて
デスクリムゾン - Wikipedia
https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%A0%E3%82%BE%E3%83%B3
2016年半分はお世話になってますし、何より製品/サービスと現場は最高でしたのでせっかくだから書いてみようと思いました。
呼ばれて無いから空気を読まずに突撃しましょうーそっちのが楽しそうですしw
何を書くか
駅すぱあとWebサービス
を使ったネタを書くのは当然なんですが・・・
これまでのアドベントカレンダーで中の人が丁寧に説明されているので、これ以上書くことがないw
↑な投稿も見かけたのでAPI
であることのメリットがなんか出るように、re:Invent で発表された新規サービスと組み合わせて使ってみようと思います。
Amazon Polly
今年のre:Invent 2016 で発表された新サービスで Turn text into lifelike speech using deep learning
と公式で説明されています
文字列を読み上げてくれるわけですが、かなりの精度でそのまま読んでくれます。漢字もわざわざ読みを渡さなくてOKなのは楽でいいです。
東京リージョンにはこの時点では来ていませんが、今回はリアルタイムで利用するわけではないので問題にはならないと思います。
使ってみる
AWS マネジメントコンソールにログインして Polly
のページに移動すれば、利用することができます。
今回利用するのはテキスト読み上げ機能
になるので、マネジメントコンソール上でテキストを入力してどのような感じになるのか試してみます。
実際にはAPIで取得した文字列をAPI/SDKを通じて、このテキスト読み上げ機能を利用することになります。
前提
駅すぱあとWebサービス
の利用開始についてはすでに詳しく書かれているので、割愛しようかと思いましたが・・・
↓からの申し込みだと半年前と変わりがなければ温かみのある手作業
でアクセスキーを発行しているはずなので、基本的には営業日基準での対応となるはずです。
オープンデータ
をうたっているのに申し込みが必要で待ち時間があるのも、
個人的には違和感ありますねぇ。データカタログサイト
に掲載してみたりしたらいいのに。
オープンデータ - Wikipedia
https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%83%87%E3%83%BC%E3%82%BF
とは、言っても仕組みは簡単に変わらないので・・・今後に期待しつつ今回はdocomo Developer support
を利用しました。
docomo Developer supportは、ドコモやパートナー企業が持つ様々なアセットを「API」として汎用化して提供し、開発者へ展開することで、新たな事業の創出を推進する協創プラットフォームです。
と書かれている通り、駅すぱあとWebサービス以外にもたくさんのAPIが利用できます。
登録も簡単でSNSアカウントでのログインも可能です。注意が必要な点は
- 検証用/開発用に発行されるアクセスキーには90日の有効期限が付いている
- 駅すぱあとWebサービスを含むいくつかのAPIを利用するには
法人情報登録
が必要になる 法人情報登録
とは? 所属する会社の住所やらを登録するだけで法人として会社で登録してもらう必要はない。- アカウント単位で所属の会社情報を入力するだけである
- このためフリーランスの方は登録が難しいかもしれない
という感じになります。ユーザー登録してAPIの利用申請を行うとAPIにアクセスするための情報が発行されます。また、エンドポイントもこのサービス専用になるようです。
簡単に利用できるので検証/検討段階ではこれで必要十分な気がします。さすがNTTドコモ!!素敵です。
まずは
Amazon Polly に入力するための文字列を作る必要があります。駅すぱあとWebサービスで何らかの経路を検索して、その結果を適当に口語風にしたものを利用したいと思います。
簡単に書くと↓な感じ?
入出力は色々面倒なので、みんな大好きSlackを利用します。
Outgoing Webhooks
を設定して 乗換
のキーワードに反応するようにしました。Slackに設定するアイコンは以下のWebからAndroidアプリ版のものを利用させてもらいました。
Amazon API Gateway + Lambda の組み合わせは動作させるのに楽なのでPython Serverless Microframework for AWS (chalice)
を利用します。
chaliceについては↓で書いているので参考になれば。
chalice はこういうちょっと試したい時には本当に楽でいいですねーまだまだ対応しているAWSサービスが少なかったりとかしますが・・・
実際に今回使用した chaliceのバージョン0.5.0
ではまだAmazon Pollyに未対応なので、↑のBlogの中に書いてあるように自動でポリシーが生成できません。
手動でポリシーを生成してかつ、デプロイ時には--no-autogen-policy
オプションを指定する必要があります。
また、Lambdaの環境変数も利用しているのですが、こちらも未対応のため別途AWSマネジメントコンソール等から設定が必要となります。
AWS Lambda の新機能 – 環境変数とサーバーレスアプリケーションモデル (SAM) | Amazon Web Services ブログ
https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-environment-variables-and-serverless-application-model/
AWSマネジメントコンソールから環境変数を保存しようとすると、権限不足で保存できないエラーが出ました。
どうやら以下2つの権限を追加する必要があるようです
- ec2:DeleteNetworkInterface
- ec2:DescribeNetworkInterfaces
権限を追加したところ、環境変数の保存が出来るようになりました。
しかし2016/12/23
に確認したところ上記2つがなくても大丈夫な感じになってそうです。もしエラーが出たとしたら追加する感じで大丈夫そうです。
経路検索
駅すぱあとWebサービス の経路簡易探索
APIで経路検索を行います
必須なのは出発
駅名と到着
駅名の2つだけなので、前述のSlackで乗換 高円寺 飯田橋
のような形で入力されたものを利用します。
これで現在時刻に出発する経路検索を利用できるようにします。
で、検索自体は簡単に出来るのですが・・・問題は結果のレスポンスデータ
・・・久しぶりに使いましたけど相変わらずの面倒臭さがw
難しいと言うわけではないので、地道に必要な値を取得していってください。今回は単純化するために、検索結果の一番最初の経路を口語調にしています。
実際にLambdaからAPIを呼び出してる部分は↓のように非常に簡単です。
def searchCourse(eki_from, eki_to): url = "https://api.apigw.smt.docomo.ne.jp/ekispertCorp/v1/searchCourse" params = {"APIKEY": API_KEY, "from": eki_from, "to": eki_to} headers = {"Accept": "application/json"} response = requests.get(url, params=params, headers=headers) print('searchCourse={}'.format(response.text)) return response
口語調にする部分は出来る範囲でそれっぽくなるように頑張って編集していますが・・・ちゃんとやるならここも単純に編集するだけではなく、工夫していく必要がありそうですね。
SynthesizeSpeech
今回の本題であるAmazon Polly SynthesizeSpeech
APIを使うわけですが、Lambdaから利用する場合はSDK経由で利用できるため非常に簡単です。
Polly — Boto 3 Docs 1.4.2 documentation
http://boto3.readthedocs.io/en/latest/reference/services/polly.html#Polly.Client.synthesize_speech
実際にLambdaから呼び出してる部分は↓のように簡単です
client_polly = boto3.client('polly', region_name="us-east-1") response = client_polly.synthesize_speech( OutputFormat='mp3', Text=msg, TextType='text', VoiceId='Mizuki' )
1点だけ困ったのはLambdaは東京リージョンにデプロイしていたので、東京リージョンに来ていないAmazon Polly をboto3.client('polly')
として呼び出すとエンドポイントがない
とのエラーが出ます。
これがchaliceのエラー処理で元のエラーを消してしまう仕様と相まってなかなか気が付きませんでした・・・
これを回避するには、boto3のクライアントを作成する際に引数でリージョンを渡すこと解決できます。クレデンシャルについても同様に引数に与えることで別のものを利用することができます。
Credentials — Boto 3 Docs 1.4.2 documentation
http://boto3.readthedocs.io/en/latest/guide/configuration.html
また、蛇足になってしまいますがboto3のドキュメントを見てみるとAmazon Polly にgenerate_presigned_url
が用意されているのが確認できます。
Polly — Boto 3 Docs 1.4.2 documentation
http://boto3.readthedocs.io/en/latest/reference/services/polly.html#Polly.Client.generate_presigned_url
generate_presigned_url
を利用すれば、一時的にAmazon Pollyの機能を外部から利用することが可能になりますしいろいろと夢が広がりますねぇ
音声保存
Amazon Polly SynthesizeSpeech API で作った音声ファイルをS3に保存します。Slackにレスポンスとして投稿したいので、ただ単純に保存するだけではなくS3のgenerate_presigned_url
を利用して一時的にアクセスを許可しておきます。
現在時刻で検索した結果の音声ファイルなので、数時間後に急いで聞き直したいというような要望はなさそうなので有効期限はデフォルトのまま60分になっています。
S3 — Boto 3 Docs 1.4.2 documentation
http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.generate_presigned_url
1点だけ困ったのは ClientMethod
に許可する操作(今回はget_object
)を指定するわけですが、この指定する操作についての権限がポリシーに設定されていない場合でもgenerate_presigned_url
の実行自体はは成功するようです。
しかし、実際にアクセスしてみると権限が付加されていないためファイルが見えないという自体になりました・・・許可する操作についてもポリシーにて許可が必要となるっぽいのでご注意ください。
結果
これでようやくSlackで乗換 高円寺 目黒
のような入力反応して、Amazon Pollyがそれっぽく話してくれるようになりました!!
実際に利用してみると・・・
高円寺ー飯田橋
の検索結果(途中乗換なし)高円寺ー目黒
の検索結果(途中乗換あり)高円寺ー虎ノ門二丁目
の検索結果(バスを含む)駅名が一意にならない場合
の検索結果
実際の音声ファイル
mp3
のままだとTwitterにUPできなかったので、音声ファイルのみのmp4
動画に変換してUPしてあります。以下のサイトを利用しました。便利。
高円寺ー飯田橋
の検索結果(途中乗換なし)高円寺駅を04:43にJR中央線・東京行きにて出発すると、飯田橋駅には05:03にJR中央線・東京行きにて到着します。片道220円で20分かかります。
twitter.comRoute search result of "高円寺" to "飯田橋" talked by Amazon Polly. pic.twitter.com/TNbeF077S7
— Manabu Uchida (@uchimanajet7) 2016年12月23日高円寺ー目黒
の検索結果(途中乗換あり)高円寺駅を04:43にJR中央線・東京行きにて出発すると、目黒駅には05:14にJR山手線内回り・渋谷・品川方面にて到着します。片道220円で31分かかります。乗換が途中1回必要で新宿駅にて乗り換えてください。
twitter.comRoute search result of "高円寺" to "目黒" talked by Amazon Polly. pic.twitter.com/BXcZjxdivq
— Manabu Uchida (@uchimanajet7) 2016年12月23日高円寺ー虎ノ門二丁目
の検索結果(バスを含む)高円寺駅を07:01にJR総武線・千葉行きにて出発すると、虎ノ門二丁目/東京コミュニティバス停には07:49に港区・ちぃばす(芝ルート)・田町駅東口行きにて到着します。片道440円で48分かかります。乗換が途中3回必要で四ツ谷駅、赤坂見附駅、新橋駅、新橋駅/東京コミュニティバス停にて乗り換えてください。
twitter.comRoute search result of "高円寺" to "虎ノ門二丁目/東京コミュニティバス" talked by Amazon Polly. pic.twitter.com/0kvYZJ54no
— Manabu Uchida (@uchimanajet7) 2016年12月23日
以上のように、それっぽく返答するようになったと思います。中の人がもっと複雑な検索を試した場合はどーなるかちょっとわかりませんがw
まとめ
- Amazon Polly で話してもらうことはできた
- 思ったよりもずっと簡単に利用することができる
- 抑揚とかは利用するシーンで適宜利用する必要がありそう
- このままでは実用には足らないが、いろいろと工夫をしていけば面白そう
- 例えば1つの検索結果でも、短い音声ファイルを複数作った方が良さそう
- 音声ファイルが長いと目的の個所を聞くまでに時間がかかる
- 短い音声ファイルなら繰り返し再生することも容易にできる
- 現実味がありそうなのは経路の区間ごとの音声ファイル化かな?
- 駅すぱあとWebサービスを使うのは簡単
- でも、JSONをいろいろ操作するのは面倒
- 特に
配列
だった要素が単一
になるとか、要素の下が急に詳細に変更になるとか検索結果によって違う場合があるのが困る - いちいち対処するのは面倒だし手間なので、ぜひ
SDK
の提供を希望!
- 現状はdocomo Developer supportの方が便利なので、本家の今後に期待しています。
- 動かしただけで終わってしまっているが、Lambda経由で呼べることには意味がある
- これにより非同期や定期実行などを行うことができる
- 会社でお使いのカレンダーやらSalesforceと連携ができると、
めんどくさい
ことをいろいろと自動化できそうですね。 - しかも結果やら入力やらはSlackと連携してしまえば楽そうです
- 個人的にも勉強会に出かけることも多いので試しに作ってみたいところです
- 今回使ったプログラム類はGitHubに上げました。簡単なので必要ないかもしれませんが試してみたい方は覗いてみてください。
今後
- 今年のre:Invent 2016 で発表のあった
Amazon Lex
をはじめとした音声によるコントロール VUI
という表現を使っていますが非常にわかりやすい入力方法ですよねAWS re:Invent 2016: From VUI to QA: Building a Voice-Based Adventure Game for Alexa (ALX305) from Amazon Web Serviceswww.slideshare.net
www.youtube.com- 話すだけで操作ができるのは、詳細な説明なしでも使い始められますし
- 駅すぱあとWebサービスのようなものはこれと相性が良さそう
- 手軽に使ってもらえるようにいろいろノウハウが蓄積できると面白そう
- 今後の幅広い応用を期待しています!
- 実際に音声入力ではありませんが他社だとこんな事例も出始めましたね
ナビタイムジャパンのLINE公式アカウントにて終電・始発検索機能を追加|ナビタイムジャパン
http://corporate.navitime.co.jp/topics/pr/201612/21_3997.html - 既にこんなことが可能なものもあるようですね
- 遠くない未来に実現しちゃうかも知れませんね!
宣伝
絶賛人材募集中らしいですよ!製品/サービスと現場は最高でした。あとはよく知らないw
また、勉強会の会場も提供しているようですので問い合わせてみてはいかがでしょうか?
ヴァル研究所の勉強会の会場 | Doorkeeper
https://www.doorkeeper.jp/%E4%BC%9A%E5%A0%B4/vallaboratory
まだまだ続く「ヴァル研究所 Advent Calendar 2016」
12/25 の最終日までまだまだ続く ヴァル研究所 Advent Calendar 2016
明日以降の投稿も楽しみですね!
今回は空気読まず参加してしまいましたが、中の人の素晴らしい投稿の方が良いと思うので来年は中の人の豊富な投稿を楽しみにしております。
以上になります。
アップデートで進化する #iot #SORACOM #ソラコムサンタ
★この記事は「SORACOM Advent Calendar 2016」の22日分のエントリーになります
注意
- 機能/サービスの検証とスクリーンショットの取得は
2016/12/17
に行いました。 - それ以降に変更が加えられた場合は結果が異なる可能性がありますのでご注意下さい。
はじまり
ある日 こんなのありますよ!
とのメッセージと上記のURLが送られてきましたw
名指しとあらば可能なことは断らずに受けていくスタイルなので書くことにっ!
あれ、これなんか見たことある流れだw とは言え、転職した後はIoTというかSORACOMに触る機会もなかなかなく・・・
しかし、SORACOMの皆様には非常にお世話になっている&SORACOMのサービスは触っていて楽しいので何とかネタを探して行くしかない!
これまで
去年の今頃はちょうどSORACOMさんにお邪魔してトンカツ食べてた頃ですねw あれからもう1年なのかまだ1年なのか。
しかし、いまだ公開事例化ができるようなものがないっぽいのは非常に残念ですねぇ。前職の中の人は是非とも頑張っていただきたい。
他には SORACOM Conference “Connected.”
のセッションでプロトタイピング中のものを紹介してもらったりしました。
www.slideshare.net
プロトタイピングしてたものは↓な感でした。
あとは、前職の退職も決まった頃の最高に楽しかったハンズオンの会場係! いい思い出だ!
何を書くか
最近は全然SORACOMを触ってないのでネタが・・・
せっかくだから約1年前にやってたことで これどーしようかな?
と考えてたことが、この1年間のSORACOMのアップデートでどうなったのか?を書いてみようと思います。
デバイスとSIM
作っていたのは 位置情報
を定期的に送信して位置を確認するようなものでした。不特定多数が乗り降りするような動体に設置することを想定していましたので、デバイス丸ごとの持ち出しとSIMだけを持ち出される懸念がありました。
その当時に考えたのは、仕様として定期的にデータを送信するため1日に送信されるデータ量がおおよそ予測可能だったため データ通信量の監視
機能を利用して、通信料が増えたら通知して貰えば不正利用もわかるかなーと
ただ、これでも通知される範囲内で利用された場合は検知できない可能性も・・・デバイスとSIMをセットで管理できると楽なのになぁーと感じていました。
IMEI ロック
それから1年後の今はどうかというとデータ通信量の監視
に加えてアップデートで追加されたIMEI ロック
があります。
IMEI ロックを利用すると、デバイスとSIMを結びつけて特定のデバイスでしかそのSIMが利用できないようにロックすることが可能になります。これにより、SIMだけを持ち出された場合でも他のデバイスでの利用が不可能になります。
特別な作り込みも必要なくSORACOM のユーザコンソールから利用できるのも手軽で非常に良いですよねー
通信距離と電力
作っていたの 定期巡回
するような動体の位置把握でしたので、動体そのものから定期的に位置情報を発信して現在地を表示していました。
しかし、要件としては細かい現在位置というよりはある一定の範囲に入ったら情報を表示できれば良いという感じのものでした。
これを実現するとなると、ゲートウェイ製品を必要なポイントに立てて、ゲートウェイ単位でなんとかするとかかなぁ?ぷらっとホーム
さんの OpenBlocks
とかを使えば行けそうかなぁ? とか考えていました。
実際にWebを確認すると位置測位のソリューションを展開されているんですねーまぁーそうなりますよねー
ただコストやメンテナンスなんかの兼ね合いもあり、その当時だとこの選択ななかなか難しいなぁーという結論に・・・
LoRaWAN
それから1年後の今はどうかというと、SORACOMさんとM2Bコミュニケーションズがパートナーシップを結んだことにより、LoRaWAN と SORACOM プラットフォームとの連携が可能になっています。
LoRaWAN は通信できる範囲が広いので上手く活用できればゲートウェイの数が減らせるのでコストやメンテナンス周りでマッチする可能性もありますね。
現在はまだPoCキットの提供となっていますが今後が楽しみですね。
まとめ
- 1年前に比べてアップデートで進化しているSORACOM
- 使っていればそれだけで新しい解決方法が提示されている
- 当然ながら利用する側もこのアップデートになるべく追随して恩恵を受ける方がいい
- LoRaWAN のようなこれまでの発想と違った技術とも連携が取れる
- 大型の機能追加以外も多くサービスとして完成度が上がっている
- 最近SORACOM触れてないので久々に楽しかったです
- 今後の機能追加とアップデートも期待してワクワクしながら待っています!
なぜか・・・
twitter.comSORACOM #AdventCalendar 2016、14日、19日、22日にサーバーワークスのメンバーが参加させていただきます!!おたのしみに☆ #Qiita https://t.co/OPC0Lh96EF #swx #iot
— サーバーワークス (@serverworks) December 12, 2016
なぜか会社の公式Twitterがハードルを上げてきたので、他にも何かネタを考えないとかなぁーと。せっかくなので 位置情報取得
を使って何かしてみようかと思います。
前提
SORACOM Air
を利用するのは当然なので、使える機器を家で探したわけですが・・・↓ ぐらいしかなかった・・・ドコモさんの機器が家にないのがわかりましたw
使えるのは標準SIMだったので、素敵なアダプターで変換をして利用しました。このノベルティー実用性も高くて素敵ですよね。
あとは位置情報を収集するための簡単なプログラム書いて SORACOM Air
で送信するだけですね!
SORACOM Harvest
2016年11月30日に追加された新サービスで IoT デバイスからのデータ収集および可視化サービスです
と公式で説明されています
SORACOM Airを利用して送信するので安心かつ自前でデータ保持や可視化の環境を持たなくてもSORACOMがすべてやってくれるというフルマネージドのサービスですね。
簡単かつ気軽に利用できるのは本当に便利ですばらしいですね
で、今回はこれに位置情報を送ってみようと思います。 それなんか意味あるの?的な結果になりそうですが・・・
使ってみる
SORACOMのサービスは大変親切な Getting Started
が用意されているので、↓に沿って進めていきます
ドキュメントが丁寧に書かれているので特に迷うことなく使い始めることができますね。
位置情報
今回は手軽に位置情報を取得したいので、HTML5で利用できる Geolocation API
を使って取得を行います。
Geolocation API Specification 2nd Edition
https://www.w3.org/TR/geolocation-API/
継続的に位置情報を取得したいので navigator.geolocation.watchPosition
を利用ています。
実際の利用法はGoogle先生で調べれば色々出てきますが非常に簡単に利用できます。
1点注意が必要なのはブラウザ側の制限で位置情報を取得するには HTTPS
が必須となっています。
今回はローカルで検証を行うため file:///
から始まるものにはこの制限は関係ないようです。通常と同じように位置情報取得を許可してもらえれば取得が可能になります。
実際に試してみる
簡単なHTMLとJavaScriptで位置情報を取得できるようにして、実際にSORACOM Harvest
に向けて送ってみましたが・・・ローカルだと以下のようなエラーが
ローカルだからかなぁ?と思いS3とCloudFrontでHTTPSで公開して試してみると
SORACOM Harvest のエンドポイントが HTTP
なのでHTTPSとの混在を怒られて送れないらしいので、ブラウザを↓のように操作してHTTPでも読み込むようにします。
しかし、残念ながらまだエラーが出ます
最初と同じ CORS
のエラーですね・・・これはSORACOM Harvest のエンドポイントが対応してないってことなのか。残念。
結局
通常のWebであれば、Amazon API Gateway などを手前にかぶせてCORSに対応してしまうこともできるのですが、SORACOM Harvestのエンドポイントにアクセスするには、SORACOM Air経由である必要があるわけなので・・・今回はこう言った手法は使えないことに。
ただ今回はローカルだけで検証するつもりだったので、JavaScriptから位置情報をPOTSする先をローカルに立てたサーバーし、そのサーバーからSORACOM Harvestのエンドポイントに再POSTすることにしました。
golangで簡単なプログラムを組んで上記のことを実現してますが、よく考えたらDockerでnginx動かしても簡単で良かったかもしれないですね。
で、実際に位置情報をSORACOM Harvestに入れたら↓になりましたーやはりあんまり意味なしな結果にw まーそりゃそうだ。
しかし、雑にJSONを送るだけで可視化して値も見ることが出来るのは手軽でいいですねーSORACOM Funnelとは違った便利さがあって素敵です。
まとめ
- SORACOM のプラットフォームを利用していると、プラットフォーム側のアップデートによりそれまで不可能だったことが可能になったり、複雑な仕組みが必要なくなったりする。
- AWSなどのクラウドプラットフォームと同様に、SORACOMのプラットフォームもマネージドサービスを積極的に利用して楽をしよう
SORACOM Harvest
は非常に手軽にデータの送信、蓄積、可視化を行える- あまり無いかもしれないが、ブラウザのJavaScriptからSORACOMのエンドポイントにデータを送信する場合には
CORS
に注意する - スマホ+ブラウザでSORACOMサービスを利用することは、今後ありそうなので解決方法があれば知りたいです。
- 今回使ったプログラム類はGitHub上に上がってます。簡単なので必要ないかもしれませんが試してみたい方は覗いてみてください。
#ソラコムサンタ
今年も #ソラコムサンタ
がやってきてくれるとのこと。
せっかくなので細々してるお願いをまとめて書いてみました。
- 手軽に使えるSIMフリーの機器があると嬉しいです。
- 今回も検証そのものよりも使える状態にするまでが時間がかかった・・・
- IoTでは遭遇する機会はなさそうですが
CORS
の回避ルートが欲しいですSORACOM Beam
経由ならもしかしたら!と思ったけどダメだった・・・- 多少手間がかかる方法でもなんとかなる道があると嬉しいです
- ユーザーコンソールの検索で
ワイルドカード
が使いたいです- prefix 付きで名前をつけても完全一致以外は検索できないっぽい?
- 検索文字列がなくなった後の再ロードがちょっと重い
- この辺はSIMの登録数とかPCのスペックとかに関係ありそうなので、一概には言えなさそう・・・
- ユーザーコンソールで地図を表示して欲しい。
- グローバル・カバレッジのユーザーコンソール画面ですでに表示されているっぽい?
各SIMの詳細画面では、基地局情報が取得できる場合には地図上での位置を表示したりセッション情報(いつ接続したか、切断されたか)を表示することができます。 blog.soracom.jp
- 地図があれば地図上から
ジオフェンシング
の範囲を指定したい - これが出来ると、ある一定の範囲から出たら/入ったらでトリガーが引けそう
- そうなると、動いちゃいけないデバイスがある範囲から動いたら通知とか、家に帰ってきたから3GをOFFにするとか出来そう
- もちろん Harvest で今回やったみたいに動体管理が出来ちゃうとしたら作り込みいらなくて最高
- グローバル・カバレッジのユーザーコンソール画面ですでに表示されているっぽい?
すでに実現済みで私が知らないだけっていうのもありそうな気もしますが・・・その場合はお手数ですが教えていただけると大変助かります。
宣伝
弊社サーバーワークスは SPS 認定済インテグレーションパートナー
です。SORACOMを利用したIoTについてご興味ある方は是非お問い合わせください。
まだまだ続く「SORACOM Advent Calendar 2016」
12/25 の最終日までまだまだ続く SORACOM Advent Calendar 2016
明日以降の投稿も楽しみですね!
以上になります。
採用イベント『サバノミソニ』#10 で話してみた #サバノミソニ #swx
前回のイベントから約5ヶ月ぶり2回目のお話の機会をもらったので、前回とほぼ同じスライドですが今思うことを相変わらずのゆるさで話してきました。
今回は
前回と違いタイトルが決まってたりw若干雑な依頼とかではなく・・・
1週間ぐらい前にSlackに12/21水曜の19時~って勉強会行っちゃいますか?
とのメッセージが。確かにその日は勉強会の予定があり、会社のカレンダーにも記載されていました。
どーやらその日に会社でイベントをやるそうで、ありがたいことに前回の発表と同じもので発表して欲しいとのこと。
名指しとあらば可能なことは断らずに受けていくスタイルなので発表することに!というか、話すネタさえあればそんなに大変なことでもないですしね。
実際に
今回は15分と前回の発表より少し長めですが、資料は現状に合わせて細かいところを見直しだけにしました。実際にはいろいろ足してみたんですが・・・結局削除して無駄になることにw
会場には若者からおじさんまでと、今回は幅広かったように思えました。
しかし、この予定のほうが後から決まったのに偶然にもアドベントカレンダーの担当日に発表とはw
内山さん
の投稿は宣伝しませんでしたがw アドベントカレンダーの宣伝は入れておきました。会社の公式からの扱いも合わせてw
前回から
前回から変化したことといえば、私自身がリモートOKになったことでしょうか? これは本当にありがたくルール内であれば非常に自由度も高いので助かってます。
こういう部分はリモートやるぞ!
という特別な扱いではなく、ごくごく自然に馴染んでるからかなぁ?と。
また、今回今日はここで15分話すために会社に来たぜー
と言ったら、外野からリモートでプレンゼンしたら良かったんじゃね?
とツッコミがあって・・・そんな全然思いつかなかったw
まだまだ、自由な発想や体験が足りないようなのでこの先生きのこるためには!
で先に進んでいこうと思いました。
お待ちしております!
サーバーワークスでは絶賛仲間を募集中です。ご興味ある方は是非お声がけください。
以上になります。
Amazon Rekognition の Demo を試してみた #aws #swx #jawsug
★この記事は「サーバーワークス Advent Calendar 2016」の21日分のエントリーになります
注意
- 機能/サービスの検証とスクリーンショットの取得は
2016/12/11
に行いました。 - それ以降に変更が加えられた場合は結果が異なる可能性がありますのでご注意下さい。
- 画像が多めになってます。(しかも
おっさん
!!)
はじまり
ある日Slackに 書くよね😸?
の一言と上記のURLが送られてきましたw
名指しとあらば可能なことは断らずに受けていくスタイルなので書くことにっ!
とは言え、入社して半年で何をネタに書こうかなぁーと・・・ これまでサーバーワークスに関してだと↓な感じかぁー
何を書くか
サーバーワークスに関わることであれば何でもOK!!
と言うことなので、なんでもいいらしいがやはり大好きなAWSネタは入れたいところ。
サーバーワークスに入ってしばらくした後に、自己紹介のLTで画像認識を使ったネタをやったことを思い出したので、同じことを今回はAWSでやってみようかと思います。
Amazon Rekognition
今年のre:Invent 2016 で発表された新サービスで Deep learning-based image recognition
と公式で説明されています
題材が こけし
と謎めいていますが弊社のBlogでも紹介しています
これまでAWSではこの分野のサービスは存在しませんでたが、ようやくサービスとして利用できるようになりました。
ちなみに他のクラウドベンダーは以下のような感じです
使ってみる
AWS マネジメントコンソールにログインして Rekognition
のページに移動すれば、Demoを利用することができます。
今回デモ環境で利用してみるのは Face comparison
です。よーするに顔が似てるかどうかってやつですね。
デモを利用するだけならこれで準備完了で、あとは比較した顔画像を用意するだけ!今回は前述の通りLTでやった画像をそのまま利用します。
前提
LT全体はどーでもいいので、画像比較の部分だけ抜粋して何をやったかを少し。
↑の画像のように新旧画像w が本人として認識されるかを、マイクロソフトが提供している以下のサイトを利用して試してみました。ちなみに画像に書いてある通りにFacebookの自動タグ付けは反応しませんでしたw
ただ、このサイトで使われているのは
Powered by Microsoft "Project Oxford"
となっていることから、前述した Microsoft Azure Cognitive Services
と同等なのかはわかりませんのでご注意ください。
TwinsOrNot.net
上のリンクは以下にリダイレクトされていますがどーなんでしょうか??
実際に TwinsOrNot.net
と Amazon Rekognition のDemo
を試してみるのが良さそうなのでやってみました。
TwinsOrNot.net での結果
- 新旧比較
本人なのに・・・なんなのこの微妙な結果は・・・
- 100%一致を目指す最近の画像同士
安心の 100%
を確認した。
Amazon Rekognition のDemoでの結果
- 新旧比較
本人なのに!! ゼロ ってなんだよ!ゼロ・・・
- 100%一致を目指す最近の画像同士
95%
!!5%の違いはどこにあるのかー5%分また膨らんだのか!?
それでも新旧の比較よりはだいぶマシな感じがするから不思議w
まとめ
新旧比較
では結果に大幅な違いが出た- 最近の画像同士では両方同じような感じ
- 画像認識などの技術に明るくないので想像するに、特徴点の比較数が異なっていそう??
- Amazon Rekognition の方が差が極端なので特賞店の比較数が少ないのかもしれない
- まだまだ発表されたばかりのサービス+Demo環境なので今後に期待したい!
- 検証するための良い画像は手元にあるのでw アップデートが楽しみです!
補足
twitter.comRekognition で compare-faces するときは similarity-threshold=1 とか適当な値をリクエストしておかないと、顔が似てないと足切りで similarity がレスポンスされないので注意な。https://t.co/6MaKMsPGSK
— しみず@AWS芸人 (@shimy_net) 2016年12月10日
CompareFaces - Amazon Rekognition
http://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
↑こんな話を目にしたので、Amazon Rekognition のDemoで一致が極端なのはもしかしてこれかっ!と思いみてみると・・・
ちゃんと "SimilarityThreshold": 1
が付加されたリクエストが送られてるっぽいと。
あーやっぱり本人なのに似てないということかw
サーバーワークスなのにネタ少なめじゃないですか?
と、言われる可能性を少しだけ考慮してネタを入れておきますw
初めてお会いした方にごくごく稀にですが 内山さん
と呼び間違えらることがあります。多分ですがTVで活躍されている 内山くん
とシルエットが似ているからでしょうかねぇ?
なので、今回はその 内山くん
とどのぐらい似ているかチェックしてみようじゃありませんかっ!!
前提
その 内山くん
の意識合わせをしておきましょう。イメージしている人が違ったら困りますし。
内山信二 - Wikipedia
https://ja.wikipedia.org/wiki/%E5%86%85%E5%B1%B1%E4%BF%A1%E4%BA%8C
今回の検証で利用した画像は、以下のご本人の公式BlogにUPされていたものを利用させていただきました。
TwinsOrNot.net での結果
- 内山くんの2種を比較
安心の100%一致なので次はいよいよ 内山さん
と 内山くん
の比較をw
- 内山くん と 内山さん の比較
最高で 78%
とかなり高いスコアが!!!これはどういうことなのw
自分の新旧比較でも 77%
とかなんですけども・・・これはもう似ていると言って差し支えないかもしれないw
- 内山くん(めがね有り) と 内山さん の比較
おい、100%の一致率のがあるぞw どーいうことだよww
メガネの有り/無し でだいぶ結果がかわりました。100%の一致はどーいうことなのよ。 他のも一致率は上がっているし・・・笑いの才能あるなぁーマイクロソフト!!
Amazon Rekognition のDemoでの結果
- 内山くんの2種を比較
本人なのにゼロ 再び・・・鬼だなw
- 内山くん と 内山さん の比較
全部ゼロ!清々しいぐらいにゼロになりますねーやっぱり結果が極端に出る感じがあります。
- 内山くん(めがね有り) と 内山さん の比較
こちらも全部ゼロ!残念ながら 内山くん
= 内山さん
の面白結果再びならず!
まとめ
- おっさんの顔画像多めで本当にごめんなさい・・・
- やはり2つのサービスで結果がだいぶ異なる
TwinsOrNot.net
だけで見ると内山くん
=内山さん
となる結果も!!あ、どうも内山ですw- メガネ有りと無しでのせいなのか結果が大幅に変わったのが興味深い
- Amazon Rekognition のDemoはこの場合も0/1のような感覚の出かた
- 両サービスともにまだまだアップデートの余地があり、やっぱり今後が楽しみ。
- Amazon Rekognition のDemoはWebで拝見することも多い勇者様もゼロになっていたので現時点では他の方も似たような状況なんだなぁーと
宣伝
サーバーワークスでは絶賛仲間を募集中です。ご興味ある方は是非お声がけください。
まだまだ続く「サーバーワークス Advent Calendar 2016」
12/25 の最終日までまだまだ続く サーバーワークス Advent Calendar 2016
明日以降の投稿も楽しみですね!
以上になります。
気がつけばもう4ヶ月が経過した件 #swx
今日は
今日は10月14日
みんな知ってる鉄道の日ですね。
鉄道の日
https://ja.wikipedia.org/wiki/%E9%89%84%E9%81%93%E3%81%AE%E6%97%A5ja.wikipedia.org
6月16日
から株式会社サーバーワークス
で働き始めて、気がつけば早4ヶ月になります。何の通知もなかったので知りませんでしたが、気がつけばコーポレートサイトにもメンバーとして載ってたりします。この使われている写真が欲しいなw
笑いすぎてて目がなくなってるじゃんw とか思ったりもしますが笑ってなくても同じようなものだという話も・・・
無事に試用期間も終わりクラウドワークスタイル
と呼ばれているリモート勤務を行えるようになりました。クラウドワークスタイルを含めたサーバーワークスのはたらき方は、中の人が話スライドを見るとわかりやすいかもしれないです。例えば↓とか。
試用期間の終わりに簡単な面談?振り返りがあるのですが、ちょうど入社して約1ヶ月で話した内容も自分で振り返りつつの面談だったので、このタイミングで自分が忘れないようにまとめてみました。
何で?
試用期間3ヶ月の終わりに代表と面談する時間が設けられていて、話のネタにするためのアンケートなんかもあったりします。 このタイミングで面談するのは、前職と現職の違いが明確になる時期であるのでそこでカイゼン案や意見が出ることを期待しているとのこと。
細かいアンケート内容はアレですが・・・ざっくり全体として
- 前職と現職の違い
- 前職の良いところ
- 現職の良いところ
- 現職のカイゼン点
- 今後やりたいこと
- 印象の違い
と、言う感じでした。 1 on 1 で話せる機会を設定しているのと、カイゼンのためのミーティングというのはいいなぁーと感じました。こいうのこれまでなかったなぁw
リモートワーク
実際にリモートワークをやってみて感じたのは
- 自宅から移動しないので楽
- 通勤時間分を作業できる
- 当然自由なこともできる
- 自宅から出ないので引きこもり気味に
- お昼にラーメン食べる機会へった
- 健康になるかどうか知らんw
- 勉強会への参加頻度も下がった気がする
- 煮詰まったときにいろいろできる
- 積み本消化とか
- 単純に休憩だけじゃなく風呂に入るとか
- slackやらgithubでのやり取り楽
- 非同期でのコミュニケーションなので返答ない時は他のことをする
- 作業を切り替えるタイミングがある
- ミーティングもリモート済むのは助かる
- 社内勉強会も中継されるので参加可能
- 対面ではないので雰囲気がわからないので長引くこともある
- 思いついた時に作業できる
- 仕事と私事の区別が曖昧になることもある
- 細かいことを気にしてるとダメな気がする
時間の自由
は自分のペース
で作業できることになるので、非常に有難いですねーこの1点だけ切り取ってみても、転職してよかったと感じます。
まとめ
なんかよくわからん感じになってますが、常にカイゼンを続けて変化に柔軟に対応して成長を続けられるのはすごいことだなぁーと
まー当然100%マッチしてるということはないのですが、前に比べたら余計なことを気にせずいろいろ出来る環境にいることは確かだなと。 今後は前に関わってた&興味があること/分野にも可能な範囲で手を伸ばしていきたいものです。ゆるーくですがw
またどこかでお会いすると思いますが、その時はよろしくお願いいたします。
以上になります。
Slack+Chalice(API Gateway+Lambda)を使ってHerokuのコマンドを実行してみた #slack #aws #chalice #lambda #heroku
chalice(Python Serverless Microframework for AWS)を使って Content-Type: application/x-www-form-urlencoded
のPOSTリクエストを受けるところまでは確認済みなので、今回はこれを使ってやりたかったことにチャレンジしてみました。
書いてる間にバージョンが0.3.0
に上がっていました・・・試したのは0.2.0
になりますので差異があったらごめんなさい
きっかけ
仕事で Heroku
を使う機会が増えている今日この頃です。今までこんなに触る機会がなかったのでなかなか楽しく作業しております。
Heroku は多くのAdd-ons
があり、無償で利用できる物もあります。
当然今のプロジェクトでもいろいろと利用しているのですが、その中でHubotの無償運用なんかでおなじみのHeroku Scheduler
を利用しています
Heroku Schedulerの説明を確認すると
このような一文が・・・
Scheduler is a “best effort” service
ですってよ!
Scheduler is a “best effort” service, meaning that execution is expected but not guaranteed. Scheduler is known to occasionally (but rarely) miss the execution of scheduled jobs. If scheduled jobs are a critical component of your application, it is recommended to run a custom clock process instead for more reliability, control, and visibility.
実際に約2ヶ月間で1回だけ実行されないことがあり、そういう場合に何かゆるい感じで対応できるといいなぁーと思ったのが作業のきっかけです。上記の文面をみればわかりますが、ちゃんと対応するならrun a custom clock process
にしろと書いてありますしねー
ちなみに、今回実行されていないことを通知したのも無償で使えるadd−onのDead Man's Snitch
になります
チームメンバーに教えてもらったのですが、今まで全然知りませんでした。結構前からあるサービスみたいですねーいやー便利。単純に払い出されたURLにGETリクエストするとチェックイン状態になり、そのチェックインを毎時/毎日みたいなタイミングでチェックして、チェックインがなければ通知してくれるだけのシンプルなサービスです。
Herokuのadd−on経由だと1つのチェックインが無償で、チェックのインターバルと通知先に制限がある状態です。通常は有償なので制限ありでも無償で使えるのはありがたいし試しやすいですよね。
インターバルの制限は今回は問題にならないのですが、通知先がmailのみとのことなので、slackのEmail integration
を利用してチームメンバーと共有可能な状態にしました
通知はされるが
Email integrationを利用したので、何かあればslackに通知がされるようになりました。Email integrationでの通知はemailを添付ファイル扱い
で通知する仕様のようです。
最初に思いついたのは
みたいな流れなのですが・・・Outgoing WebHooks
が添付ファイル部分には反応しない仕様のようです。
email文中の特定のキーワードに反応してくれたら十分なんですが、残念ながら無理っぽいようです
結局
色々試した結果Outgoing WebHooksのTrigger Word(s)
にemail
を指定してすることでemailの受信時にWebHookがかかるようになりました。これはemail受信時の投稿がemail uploaded a file:<添付ファイルのURL>
のような形式となっているので、この文中のemail
に反応してWebHookが発行されているようです。
注意が必要なのは今回は動作確認なのでemailという単語でWebHookを発行しています。Outgoing WebHooksをintegrationしたslackチャンネルで日常的にemailという単語が使われている場合はTrigger Word(s)を別のものにした方が良いかと思います。
Outgoing WebHooks の設定画面のドキュメントには以下のようなデータがPOSTされると書かれています。
token=blaNqr3fL7b8AqnwCNFW86oZ team_id=T0001 team_domain=example channel_id=C2147483705 channel_name=test timestamp=1355517523.000005 user_id=U2147483697 user_name=Steve text=googlebot: What is the air-speed velocity of an unladen swallow? trigger_word=googlebot:
実際にはこのデータがapplication/x-www-form-urlencoded
で送信されるので
token=XXXXXXXXXXXXXXXXXXXXXXXX&team_id=T0295086H&team_domain=serverworks&service_id=77430880359&channel_id=C1X85EYNR&channel_name=times-uchida×tamp=1476076555.001561&user_id=USLACKBOT&user_name=slackbot&text=email+uploaded+a+file%3A+%3Chttps%3A%2F%2Fserverworks.slack.com%2Ffiles%2Fslackbot%2XXXXXXXXXX%2F_missing__import_data_monitoring_hasn_t_checked_in%7C%5BMISSING%5D+import+data+monitoring+hasn%27t+checked+in%3E&trigger_word=email
のような形式で送信されてきます。また、今回のように添付ファイルがある場合でもPOSTデータに添付ファイルのデータが入るようなことはないようです。残念。
Please note that the content of message attachments will not be included in the outgoing POST data.
chaliceを利用する
WebHookのPOST先を作らないといけないわけですが、あまり手間をかけずに簡単に作りたいわけですね。Heroku使ってるならそれでいいじゃん!という話もありますが、chaliceでapplication/x-www-form-urlencodedが受けられるようになったのを確認したばかりなのでchaliceを使います
chaliceそのものの使い方は簡単&他に詳しく書かれているものがたくさんあるので割愛しますが、chalice (0.2.0)
以上を利用しないと上手く行かないと思うのでその点だけ確認してください
$ chalice new-project
で新規にプロジェクトを作成し、application/x-www-form-urlencodedのPOSTが受けられるよう設定します
from chalice import Chalice app = Chalice(app_name='slack_receive') @app.route('/slack', methods=['POST'], content_types=['application/x-www-form-urlencoded']) def slack(): body = app.current_request.raw_body
app.current_request.raw_body
には前述の&
で連結された情報が入っているので、この中から必要なものを取り出してあげます。
Pythonのデフォルトライブラリを利用してパースを行い、後で扱いやすいように辞書型にしておきます。
from urlparse import parse_qsl body = app.current_request.raw_body parsed = dict(parse_qsl(body))
パースした結果は以下のような状態になっていると思います
{'user_id': 'USLACKBOT', 'channel_name': 'times-uchida', 'timestamp': '1476076555.001561', 'team_id': 'T0295086H', 'trigger_word': 'email', 'channel_id': 'C1X85EYNR', 'token': 'XXXXXXXXXXXXXXXXXXXXXXXX', 'text': "email uploaded a file: <https://serverworks.slack.com/files/slackbot/XXXXXXXXX/_missing__import_data_monitoring_hasn_t_checked_in|[MISSING] import data monitoring hasn't checked in>", 'service_id': '77430880359', 'team_domain': 'serverworks', 'user_name': 'slackbot'}
必要に応じて値のチェックを行うわけですが、今回はtoken
とtext
をチェックしています。tokenに関してはLambdaのblueprintでslack関連のものを見ると、以下のようにAWS Key Management Service (KMS)
を使った例がありますのでそれをそのまま利用します。
import boto3 from base64 import b64decode ENCRYPTED_EXPECTED_TOKEN = '<kmsEncryptedToken>' # Enter the base-64 encoded, encrypted Slack command token (CiphertextBlob) kms = boto3.client('kms') expected_token = kms.decrypt(CiphertextBlob=b64decode(ENCRYPTED_EXPECTED_TOKEN))['Plaintext']
KMSを追加してchaliceにてデプロイを行うと以下のようなメッセージが表示されるかと思います
$ chalice deploy Updating IAM policy. Unsupported service: kms
開発中ということもありすべてのAWSサービスには対応してないようです。ポリシーを自動生成してくれるのは非常に便利なので、今後のサービス対応に期待しましょう
じゃーどうすんの?って話なんですが、ドキュメントを見ると手動で作ったポリシーを使う方法があります。chaliceのプロジェクトディレクトにある.chalice/polict.json
を編集してkmsの復号の権限を付加します
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1443036478000", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": [ "<your KMS key ARN>" ] } ] }
これでポリシーは問題なくなりましたが、今までと同様にデプロイを実行すると以下のような確認が行われます。この確認でYes
を選択すると上記で手動追加したポリシーが削除され、chaliceが自動生成するものに置き換わりますので注意が必要です。no
を選択するとデプロイ自体がキャンセルされます。
$ chalice deploy Updating IAM policy. Unsupported service: kms The following action will be removed from the execution policy: kms:Decrypt Would you like to continue? [Y/n]: n Error: Error when deploying:
手動で編集したポリシーを利用するためにはドキュメントにあるように--no-autogen-policy
をつけてデプロイを実行します
The automatic policy generation is still in the early stages, it should be considered experimental. You can always disable policy generation with --no-autogen-policy for complete control.
これでKMSが利用できるようになったので、slackのtokenが意図したものかどうかを確認することができます。同時にtext中に意図した文字列があるかどうかも確認を行います。
Heroku APIを利用する
ここまでで、slackからのWebHookを受けて内容を確認するところまで終了しました。次はHeroku APIを利用してHerokuのコマンドを実行してみます。
APIを利用するためには認証キーを取得する必要があります。Herokuのアカウントページで認証キーを確認しておいてください
Authentication is passed in the Authorization header with a value set to :{token}. You can find a token to use on the “Account” page (in the “API Key” section) on your dashboard or by running this command:
このAPI認証キーもKMSを利用して暗号化を行って利用します。コマンドを実行するためにはHeroku Platform API
のDyno
関連を利用します。
Herokuはドキュメントが非常に丁寧に書かれているので、ドキュメントをみれば問題ないかと思います。ドキュメントではcurl
の例が示されていますが、Pythonではrequests
ライブラリを利用しました。
Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation
http://requests-docs-ja.readthedocs.io/en/latest/requests-docs-ja.readthedocs.io
Heroku APIで指定されているHTTPヘッダー項目を付けるのを忘れなければ特別なことをする必要がなくDyno Create
でコマンドが実行できます
このAPIでコマンドを実行した場合、レスポンスについてはHTTPステータスコード201
が返却されます。
HTTP/1.1 201 Created ETag: "0123456789abcdef0123456789abcdef" Last-Modified: Sun, 01 Jan 2012 12:00:00 GMT RateLimit-Remaining: 2400
HTTPステータスコード - Wikipedia
https://ja.wikipedia.org/wiki/HTTP%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89ja.wikipedia.org
このレスポンスからだと実行したコマンドが正常に終了したかどうか判断することができません。APIで結果を確認するにはLog Session
関連を利用するのが良さそうです
Log Session Create
APIのレスポンスで得られたlogplex_url
に対してGET
を行うと実際にLogを取得することができます。
heroku[router]: at=info method=HEAD path="/login" host=hoge.herokuapp.com request_id=8184c319-ffb0-43ab-9ea7-861991176b3a fwd="XX.XXX.XXX.XX9X" dyno=web.1 connect=1ms service=7ms status=401 bytes=354\n2016-10-10T05:15:58.327710+00:00 heroku[api]: Starting process with command `python manage.py purgerequests 4 months --noinput` by uchida@serverworks.co.jp\n']
実際にはコマンド実行後に非同期でLogを確認する必要があるので、1つのLambda関数だけでなくSQSなどを利用して他のLambda関数で確認する必要があります。また、Herokuに関して言えばAdd−onで解決してしまうのもアリだと思います。
Papertrail
のようなLogを管理できるサービスを利用すればサービス上で特定のLogを検知してslackに通知することが可能です。これを利用すればコマンド実行後の状態を検知してslackに通知してしまえば結果を確認することが可能となるため、わざわざプログラムを組む必要はなくなります。楽できる方がいいですしね。
Slackにレスポンスを戻す
ここまでで、slackからのWebHookを受けて内容を確認してHeroku APIでコマンドを実行するところまで終了しました。最後にslackにレスポンスを戻して終了です。
Outgoing Webhooks | Slack
https://api.slack.com/outgoing-webhooksapi.slack.com
ドキュメントを確認するとJSON形式
でtext
プロパティの値を設定すれば良いので、requests
のレスポンスを.json()
で設定してslackに戻しています。ただし、このレスポンス中にWebHookのTrigger Word(s)が含まれていないことが前提になります。
import requests import json resp = requests.post('<URL>', data=json.dumps(data), headers=headers) result = {'text': resp.json()} return result
まとめ
ということで、これでSlack+Chalice(API Gateway+Lambda)を使ってHerokuのコマンドを実行する
ことができました。まー何に使うの?って話はありますが・・・
chaliceを使うと非常に簡単にAPI GatewayとLambdaを使うことができます。自動で生成されるポリシーも便利ですし今後も楽しみです。一方で複雑になったり大規模になったりした場合は大変かなぁーという印象もあります。他のLambdaを利用できるフレームワークもたくさんあるので使いやすいものを選択するのが良さそうです。
また、今後リリースされるというFlourish
も楽しみですね。もうすぐre:Invent 2016
が開催されますし期待しながら待っています!
Appendix
利用したchaliceのコード例
import boto3 import requests import json import time from chalice import Chalice from urlparse import parse_qsl from base64 import b64decode app = Chalice(app_name='slack_receive') kms_client = boto3.client('kms') ENCRYPTED_SLACK_TOKEN = '<your own value>' SLACK_TOKEN = kms_client.decrypt(CiphertextBlob=b64decode(ENCRYPTED_SLACK_TOKEN))['Plaintext'] ENCRYPTED_HEROKU_API = '<your own value>' HEROKU_API = kms_client.decrypt(CiphertextBlob=b64decode(ENCRYPTED_HEROKU_API))['Plaintext'] SLACK_KEYWORDS = "<your own value>" @app.route('/slack', methods=['POST'], content_types=['application/x-www-form-urlencoded']) def slack(): body = app.current_request.raw_body print('body={}'.format(body)) result = {"text": "post OK !"} slack_token = parsed_l.get('token') if slack_token != SLACK_TOKEN: result = {"text": "slack token not valid!"} return result slack_text = parsed_l.get('text') if slack_text: print('slack_text={}'.format(slack_text)) index = slack_text.find(SLACK_KEYWORDS) print('index={}'.format(index)) if index != -1: start = slack_text.find('|') end = slack_text.find('>') sub_text = slack_text[start+1:end] print('sub_text={}'.format(sub_text)) if SLACK_KEYWORDS == sub_text: print("--- same words!! ---") # call heroku API auth_str = 'Bearer {}'.format(HEROKU_API) headers = {'Accept':'application/vnd.heroku+json; version=3', 'Authorization':auth_str, 'Content-Type': 'application/json'} data = {'command':'<your own value>', "attach": 'false', "type": "run", "time_to_live": 1800} print('headers={}'.format(headers)) print('data={}'.format(json.dumps(data))) resp = requests.post('https://api.heroku.com/apps/<your own value>/dynos', data=json.dumps(data), headers=headers) cont = {'status_code': resp.status_code, 'body': resp.json()} result = {'text': json.dumps(cont)} # log time.sleep(5) data2 = {} resp2 = requests.post('https://api.heroku.com/apps/<your own value>/log-sessions', data=json.dumps(data2), headers=headers) print{'resp2={}'.format(resp2.text)} log_url = resp2.json().get('logplex_url') resp3 = requests.get(log_url, headers=headers) print{'resp3={}'.format(resp3.text)} return result
こんなエラーメッセージが出たら
$ chalice deploy --no-autogen-policy Updating IAM policy. Updating lambda function... Creating deployment package. Sending changes to lambda. Lambda deploy done. API Gateway rest API already found. Deleting root resource id Done deleting existing resources. Error: Error when deploying: An error occurred (PolicyLengthExceededException) when calling the AddPermission operation: The final policy size (20575) is bigger than the limit (20480).
issue にもありますがLambda関数自体を削除して再度デプロイを行えば問題ありませんでした。
と思ったら、冒頭にも書いた通りにバージョンが0.3.0
になり、このissueの対応が行われています。0.2.0
以下の人はバージョンを上げましょう
地味に困る
エラーが起きるとChaliceのエラー
としてraise
されるので、何が原因なのか特定しにくい。単純にimport
を忘れた場合もchaliceのエラーとなるので他の場所かと思ってしまうと言うね・・・この辺は何か改善してほしいなぁーすでにあるなら教えてください!
ChaliceViewError: An internal server error occurred.: ChaliceViewError Traceback (most recent call last): File "/var/task/chalice/__init__.py", line 207, in __call__ raise ChaliceViewError("An internal server error occurred.") ChaliceViewError: ChaliceViewError: An internal server error occurred.
以上になります
Python Serverless Microframework for AWS (chalice) でJSON 以外のPOST を受けてみた #aws #chalice #lambda
Python Serverless Microframework for AWS (以下、chalice) を利用して
Content-Type: application/x-www-form-urlencoded
のPOSTを受けてみたことを簡単にまとめてみました。
chalice は特に指定を行わない場合は application/json で受けるのがデフォルトっぽいですが、やっぱり application/x-www-form-urlencoded を扱いたいこともあるわけなので。
ドキュメントをみると
Quickstart and Tutorial — Python Serverless Microframework for AWS 0.2.0 documentation
と、丁寧に書かれているのでそのままコピペするも実行結果は
{
"message": "Unsupported Media Type"
}
API Gateway の設定がどうなっているか見てみると・・・マッピングテンプレートで application/x-www-form-urlencoded 用のテンプレートが指定されておらず application/json のみで、どんな場合もパススルーしない設定になっているというね・・・
と、ここまではちょっと前までの バージョン0.1.0 での話ですが、ドキュメントに書いてあって実現できなかったのはちょっと残念でした。
バージョン0.2.0
で、現在のバージョンは0.2.0になっており最新バージョンで再度試してみます
前回と同様にしてchaiceでデプロイを行うと、最新バージョンではちゃんとAPI Gatewayのマッピングテンプレートにapplication/x-www-form-urlencoded 用のテンプレートが指定されていました
やっと動いたよ!と思うんですが・・・いろいろやっている間にAPI Gateway側のアップデートがあり、「Lambda プロキシ統合の使用」といったリクエストをLambdaに簡単にスルーできるオプションが追加になりました
API Gateway のアップデート – API 開発を簡素化する新機能 | Amazon Web Services ブログ
https://aws.amazon.com/jp/blogs/news/api-gateway-update-new-features-simplify-api-development/
この機能を使えばContent-Typeを気にせずにLamda関数にリクエストを送れるので、今までよりだいぶお手軽な気がしますし、Lambdaのblueprintから新規作成したりすると、すでにこの機能を使ったANYでProxyを利用した接続になっています。
実際にchalice でapplication/x-www-form-urlencoded 用のテンプレートが用意された状態と、このProxy機能でスルーされた状態でLambdaに届くデータの内容を比較してみました。
送信したのは上記したchaiceのドキュメントに書かれている httpie を利用した例と同じで
http --form POST https://endpoint-hoge1.ap-northeast-1.amazonaws.com/dev/ states=WA states2=CA --debug
Proxyの場合はevent 引数に以下のような感じで入ってくる
{u'body': u'states=WA&states2=CA', u'resource': u'/proxy-test', u'requestContext': {u'resourceId': u'co8iwy', u'apiId': u'1m6791x3wk', u'resourcePath': u'/proxy-test', u'httpMethod': u'POST', u'requestId': u'6f00523f-8936-11e6-831a-e9eb40e256a5', u'accountId': u'316874585308', u'identity': {u'apiKey': None, u'userArn': None, u'cognitoAuthenticationType': None, u'caller': None, u'userAgent': u'HTTPie/0.9.6', u'user': None, u'cognitoIdentityPoolId': None, u'cognitoIdentityId': None, u'cognitoAuthenticationProvider': None, u'sourceIp': u'xxx.xxx.xxx.xxx', u'accountId': None}, u'stage': u'prod'}, u'queryStringParameters': None, u'httpMethod': u'POST', u'pathParameters': None, u'headers': {u'Content-Type': u'application/x-www-form-urlencoded; charset=utf-8', u'Via': u'1.1 064b8001bd91f53f9b5f04fba4435677.cloudfront.net (CloudFront)', u'Accept-Encoding': u'gzip, deflate', u'CloudFront-Is-SmartTV-Viewer': u'false', u'CloudFront-Forwarded-Proto': u'https', u'X-Forwarded-For': u'xxx.xxx.xxx.xxx', u'CloudFront-Viewer-Country': u'JP', u'Accept': u'*/*', u'User-Agent': u'HTTPie/0.9.6', u'Host': u'1m6791x3wk.execute-api.ap-northeast-1.amazonaws.com', u'X-Forwarded-Proto': u'https', u'X-Amz-Cf-Id': u'4meZj8EGU3Ui_FvMztZ-Y5Oh4pkz3Tm-s4wKSd1VaZ9o722piksxIA==', u'CloudFront-Is-Tablet-Viewer': u'false', u'X-Forwarded-Port': u'443', u'CloudFront-Is-Mobile-Viewer': u'false', u'CloudFront-Is-Desktop-Viewer': u'true'}, u'stageVariables': None, u'path': u'/proxy-test'}
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' のPOSTを受けて 'body': 'states=WA&states2=CA' にパラメータ文字列が入っているのがわかります
当然パススルーしてるだけなので他のContent-Typeでも問題なしなので
{u'body': u'{"states": "WA", "states2": "CA"}', u'resource': u'/proxy-test', u'requestContext': {u'resourceId': u'co8iwy', u'apiId': u'1m6791x3wk', u'resourcePath': u'/proxy-test', u'httpMethod': u'POST', u'requestId': u'a407c1a9-8941-11e6-a603-f18eaa90784e', u'accountId': u'316874585308', u'identity': {u'apiKey': None, u'userArn': None, u'cognitoAuthenticationType': None, u'caller': None, u'userAgent': u'HTTPie/0.9.6', u'user': None, u'cognitoIdentityPoolId': None, u'cognitoIdentityId': None, u'cognitoAuthenticationProvider': None, u'sourceIp': u'xxx.xxx.xxx.xxx', u'accountId': None}, u'stage': u'prod'}, u'queryStringParameters': None, u'httpMethod': u'POST', u'pathParameters': None, u'headers': {u'Content-Type': u'application/json', u'Via': u'1.1 fbd80349eadc2efc6c27a91d8ce7b321.cloudfront.net (CloudFront)', u'Accept-Encoding': u'gzip, deflate', u'CloudFront-Is-SmartTV-Viewer': u'false', u'CloudFront-Forwarded-Proto': u'https', u'X-Forwarded-For': u'xxx.xxx.xxx.xxx', u'CloudFront-Viewer-Country': u'JP', u'Accept': u'application/json, */*', u'User-Agent': u'HTTPie/0.9.6', u'Host': u'1m6791x3wk.execute-api.ap-northeast-1.amazonaws.com', u'X-Forwarded-Proto': u'https', u'X-Amz-Cf-Id': u'QYZPvi7XzpkyeWG6FUIGPvilp3mRp4uE-bw6pk8D-5jFcR2IrrlH5g==', u'CloudFront-Is-Tablet-Viewer': u'false', u'X-Forwarded-Port': u'443', u'CloudFront-Is-Mobile-Viewer': u'false', u'CloudFront-Is-Desktop-Viewer': u'true'}, u'stageVariables': None, u'path': u'/proxy-test'}
'Content-Type': 'application/json' で受けて 'body': '{"states": "WA", "states2": "CA"}' とJSON文字列が入っているのがわかります。
Lambdaコード側で Content-Type によって処理を分ける場合があれば便利かもしれないですね
chalice の場合はドキュメントに書いてある通り、JSONの場合には current_request.json_body に値が、それ以外の場合は current_request.raw_body に値が入っているそうです
The second thing worth noting is that
app.current_request.json_body
is only available for the application/json content type. In our example above, we usedapp.current_request.raw_body
to access the raw body bytes:
Chalice — Python Serverless Microframework for AWS 0.2.0 documentation
http://chalice.readthedocs.io/en/latest/api.html?highlight=current_request#request
実際に試してみると
states=WA&states2=CA
のような形で、パラメータ文字列を取得することができます。また、こちらはJSON形式でリクエストを行うとマッピングテンプレートがありませんので当然ながら
{
"message": "Unsupported Media Type"
}
となります。
まとめ
API GatewayのアップデートによりProxy機能で簡単にLambda関数を呼び出して実行できるようになっています。
一方で、chaliceはターミナル上から手軽にデプロイと確認が行え、ログに関しても見ることができます。
API Gatewayの新機能での実現とchaliceでの実現、どちらでもJSON以外のPOSTは簡単に受けられました。chaliceは今後もこの手軽な感じで進んで行ってもらいたいです。
以上。