ITと筋トレの二刀流

未だゼロ刀流

【比較】ビーレジェンド ホエイプロテイン 勝手にランキング

f:id:tatsuyashi:20190417011040p:plain:w400

いきなりですが、皆さんのプロテインを選ぶ決め手は何でしょうか?

値段、たんぱく質の量、アミノ酸スコアなどあると思いますが、私はを重視しています。

もちろん値段や成分も気にしますが、まず味が良くないと続かないですね。

モチベーションをキープするには、モチベーションを下げる要因を排除していくことが大事なのですが、プロテインの味はまさにモチベーションに関わってくるものだと思っています。一度ちょっと苦手な味のプロテインを飲んだことがあったのですが、その時はプロテインを飲むのが本当に苦痛でした・・

今私が愛用しているプロテインがビーレジェンドのプロテインになるのですが、ビーレジェンドは味の種類がとにかく豊富でしかも溶けやすいのでオススメのプロテインです。

そこで今回は、ビーレジェンドで私が実際に飲んだ中で好きな味ランキングを付けてみましたので参考にしていただければと思います。

※全て「水」で飲んだ感想です

1位 そんなバナナ風味

1位は「そんなバナナ風味」です。

ホエイプロテイン自体に牛乳っぽさがあるのですが、バナナとミルクの相性が良いようにバナナ味のプロテインは非常に美味しいです。

酸味はなく、程よい甘さだけがあって飲みやすいです。

たんぱく質目的じゃなくて、純粋に味目的で飲みたくなるプロテインです。間違いない。

付属のスプーン3杯に対しては水200〜250mlがちょうど良いです。

2位 めろめろメロン風味

2位は「めろめろメロン風味です」

バナナはなんとなくホエイと合いそうなのはわかりますが、メロン風味が意外や意外、合うんです。

「メロン」の味というよりは、「メロン味」の味です。(わかります?w)

これも酸味は抑えられていて、それでいてメロン味はしっかり付いているのでジュース感覚で飲めることができます。

付属のスプーン3杯に対しては水200〜220mlぐらいがちょうど良いです。(水少なめで)

3位 キャラメル珈琲風味

続いて3位は「キャラメル珈琲風味」です。

よくある「キャラメルマキアート」のような味で、当然ミルク系のホエイによく合います。

甘めのコーヒーが飲める人は問題ないと思います。

付属のスプーン3杯に対しては水200mlです。250mlとか入れると薄くて逆に飲めません。

4位 初恋のいちご風味

4位は「初恋のいちご風味」です。

ここまで触れてきませんでしたが、ネーミングが独特ですよねw

これはズバリ「いちごミルク」の味です。ちょっとミルク多めって感じですね。

これもあまり酸味はなく、甘すぎずちょうど飲みやすい感じに仕上げてくれています。

付属のスプーン3杯に対しては水200〜220mlです。私は薄いのが嫌なので200mlで飲んでました。

5位 南国パイン風味

5位は「南国パイン風味」です。

パインとミルクって想像つかないですよね。

飲んでみた感じ、ミルク感はだいぶ落としてくれているように感じました。

なので、やや薄いパインジュース(ほんのりミルク風味)ですね。

それほど悪くはないですが、上位に食い込むほどではなかったというのが正直な感想です。

付属のスプーン3杯に対しては水200〜220mlです。

6位 ぴちぴちハッピーチ風味

6位は「ぴちぴちハッピーチ風味」です。

また面白いネーミングをされてますね〜。

ピーチ味ということで期待していたのですが、ちょっと酸味がありました。

付属のスプーン3杯に対しては水250〜300mlです。少し多めにした方が飲みやすくなりました。

7位 すっきリンゴ風味

7位は「すっきリンゴ風味」です。

これもパイン風味のようにミルクっぽさはだいぶ抑えられていて、 やや薄いリンゴジュース(ほんのりミルク風味)となっています。

ただ、他の種類に比べて少し臭いがします。表現は難しいですが、何かが少し腐ってるような・・・

ひょっとしたらその時飲んでいた水やシェイカーが悪いかもしれませんが。リンゴだけ不思議な臭いを感じました。

あと、少しダマができやすいです。

付属のスプーン3杯に対しては水200〜220mlです。

8位 激うまチョコ風味

8位(暫定最下位)は「激うまチョコ風味」でした。

ココアやチョコ味っていうのは他社のプロテインでもよく出されていて、ホエイのミルク風味によく合うのですが、ビーレジェンドのチョコ風味はそれらに比べると物足りなかったです。

とにかく味が薄くて、、水の量は結構調整して減らしたのですが、薄味チョコ風味は解消されませんでした。

あとこちらも少しダマになりやすいと感じました。

期待値からのギャップもあって最下位とさせていただいてます。

付属のスプーン3杯に対しては水150〜200mlです。限りなく少なく。

お試しパックで先に試すのが吉

ここまでランキングをご紹介してきましたが、私のようにとりあえず1kg買って試してみるということをしなくてもいいようにお試しパックが提供されています。

色んな味が1回分ずつ入ってるみたいですね。

失敗したくない方にはちょうど良いんじゃないでしょうか?

私の方はまだ飲んでない味が結構あるので、また飲んだらランキングに追加していくようにしますね。

人の失敗は笑うものではなく感謝するもの

f:id:tatsuyashi:20190414000736p:plain:w300

みなさんは人の失敗を見てどうしていますか?
けなしたり、笑ったり、同情したり、、色々あると思いますが、僕は感謝すべきだと思っています。(もちろん、失敗による影響が自分自身に及ぶような場合があるのはわかりますが、怒りとは別で感謝もするべきです)

今回はこれまでのようなITや筋トレとは少し毛色が違う話になりますが、なぜ失敗に感謝すべきかについて見解を述べたいと思います。

愚者は経験に学び、賢者は歴史に学ぶ

オットー・フォン・ビスマルクという人の格言で

「愚者は経験に学び、賢者は歴史に学ぶ」

という言葉があります。

私が高校生のときに、当時の担任の先生が自分の好きな言葉ということで紹介してくれた格言ですが、妙に腑に落ちた言葉でした。

直訳では

愚者だけが自分の経験から学ぶと信じている。私はむしろ、最初から自分の誤りを避けるため、他人の経験から学ぶのを好む。

とされています。

誤解されがちですが、賢者も経験から学びます。ただ、歴史(=他人の経験)からも多くを学んでいるということです。

失敗は成功のもと

有名なことわざで

「失敗は成功のもと」

という言葉があります。

これは簡単にいうと、失敗したことを反省し改善することで成功につながっていくということです。

実際に身をもって経験している方も多いと思いますし、成功されている方ほど、凡人の何倍もの失敗を重ねています。

なので失敗し、失敗を活かすことは非常に重要なことです。

他の人が代わりに失敗してくれてるという考え

人生において、小さな失敗を重ねて大きな成功を掴むというのは理想ですが、

そもそもその失敗は全て自分が経験しないといけないことなのか?ということです。

そう考えると、他の人の失敗に対する見方は変わってきます。

自分がやるかもしれないはずの失敗を先に経験してくれている、と考えることもできます。

そう考えると笑えないですよね。

人の失敗に感謝し、自分の成功に活かす

限りある人生なので無駄な時間は過ごしたくないものです。

他の人が失敗してるのを笑ってバカにするだけで何も得ず、その後自分も同じ失敗をする。

これって本当に無駄な時間だと思うんです。二度手間というか。

そうではなくて、他人の失敗に対しては、自分や他の人の代わりにみんなを代表して失敗してくれているんだという気持ちで感謝して、その失敗からしっかり学び、自分の成功に活かしていきたいものですね。

それこそが「歴史に学ぶ」ということなのではないでしょうか?

f:id:tatsuyashi:20190414004103p:plain:w300

AWS認定ソリューションアーキテクト アソシエイト 試験に合格しました

f:id:tatsuyashi:20190408234102p:plain:w500

AWS認定ソリューションアーキテクト アソシエイトの試験に合格しました。

合格したてほやほやなので、どういう勉強をしたか、どういうところを重点的にやるべきか、について書きたいと思います。

ある程度基礎知識があれば参考書と模擬試験だけで十分

まず私はこの試験を受ける前に、AWS認定クラウドラクティショナーの資格を取得していました。

aws.amazon.com

この試験に合格できるレベル、もしくは業務で1、2年しっかり経験を積んでいるような人であれば、参考書と模擬試験をやれば合格は可能だと思います。

参考書は安定の2冊

私が実際に勉強で使用した2冊の参考書を紹介したいと思います。

合格対策 AWS認定ソリューションアーキテクト - アソシエイト

合格対策 AWS認定ソリューションアーキテクト - アソシエイト

合格対策 AWS認定ソリューションアーキテクト - アソシエイト

これは実はクラウドラクティショナーの試験対策として買っていたのですが、本来はソリューションアーキテクトアソシエイト用です。

覚えておくべきサービスとその詳細がわかりやすくまとめられていて非常にオススメです。

図なども含めて、書籍として非常に内容がわかりやすいと思いました。

ただ、2016年発売ということで若干内容が古いところもあるので、参考書で見た内容は一度ご自身で調べ直すのが良いと思います。

徹底攻略 AWS認定 ソリューションアーキテクト ー アソシエイト教科書

2019年の1月に発売したので、最近勉強を始めた人の中では読んでいる人が多いのかなと思います。

こちらも各種サービスについてまとめられていますが、1つ目の参考書と違うのが、サービスごとに章立てているのではなく、高可用性・コスト面・セキュリティなどで分けられており、その中で各サービスではどうかという点が書かれています。

例えば、EC2やAutoScalingであれば、

高可用性の章ではAutoScalingを使ってEC2をスケールさせて高可用性を実現するという点が書かれていますし、コストの章ではオンデマンドやリザーブドインスタンスの違いやその他の方法について書かれています。

模擬試験は必須

AWS認定試験には、公式から模擬試験が用意されています。

模擬試験とはいえ、2,000円かかってしまいますが試験の傾向がつかめるので必ず受験した方が良いでしょう。

ちなみに、他のAWS認定試験に先に合格しておくと模擬試験の無料バウチャーがゲットできるので、次の試験からは実質無料で受験ができます。 (私はクラウドプラクティショナーに合格していたので無料バウチャーを持っていました)

あとは「徹底攻略 AWS認定 ソリューションアーキテクト ー アソシエイト教科書」を買った人だけが受験できる模擬試験があるので、買った人は必ず受験してみましょう。本家の模擬試験とは若干違いますが、参考書をやっているだけでは正解するのが難しい問題もあり役立ちました。

私は参考書2冊と模擬試験2つ(本家と参考書の)だけで試験を乗り切りました。

とにかくコンピューティング、ネットワーク、ストレージ、データベースを覚えること

試験の内容についてはネタバレ禁止と試験時に約束しているので具体的には書けませんが、

  • コンピューティング
  • ネットワーク
  • ストレージ
  • データベース

この4点については非常に出題頻度が高く、かつ他のサービスに比べて深いところを聞かれるのでまずはこの4点をマスターしましょう。

コンピューティング

EC2やAutoScalingに関する問題はよく出ます。

スケールイン/アウトするときのルールや高可用性を実現するための構成などはしっかり押さえておきましょう。

ネットワーク

VPC、サブネットはもちろんのこと、特にセキュリティ面(セキュリティグループやネットワークACL)に関する問題がよく出ます。

セキュリティ的に許可して良いケース、絶対に拒否しなくてはならないケースの違いは理解しておく必要があります。

ストレージ

S3やEBSに関する問題ははっきり言って死ぬほど出ると言って良いでしょう。

S3やGlacierのストレージクラスの種類やEBSのボリュームの種類や使用されるケースはマストです。

データベース

RDSやAuroraの特徴はもちろんですが、EC2にデータベースを構築するようなケースもよく出題されます。

ユースケースにいかに紐付けられるかが問われる

ソリューションアーキテクトとして認められるかどうかという試験なので、ある要件に対して自分がソリューションアーキテクトとしてどういう設計や対応を行うかという点を考えさせられます。

なので、参考書に書いてるような単純な問題はほぼ出ません。

例えば、S3のストレージクラスに関していうと、

耐久性が高く、読み取り時に課金され、長期保管やバックアップに向いているストレージクラスはどれか?

みたいな素直な問題は出ません。意味がないからです。上記のような悩みを実際に抱えてる人はいないでしょう。

あるソリューションアーキテクトが○○なサービスを考えています。データを取り出すことはほぼありませんが、すぐに取り出せるようにする必要があります。この要件を満たす費用対効果が最も高いストレージはどれか。

  1. 標準
  2. 標準 低頻度
  3. Glacier 迅速
  4. 1ゾーン 低頻度

みたいな問題が出ます。しかも「ほぼ」のような曖昧な表現もよく出てくるので、迷いが出ることが多いと思います。

なので、単純な暗記だけではなくて、いかに様々なユースケースを想定して勉強するかが大事です。

日常の業務は全てこのような問題ばかりになってくるので、参考書で学びつつ自分でもユースケースを考えていくというのが後々の仕事に生きてきます。まぁこれはどのような試験でも同じことかと思います。「試験に合格するためだけの勉強」にならないためにも。

試験の時間配分は気にする必要なし

人によるかもしれませんが、65問で130分用意されているので1問につき2分ぐらいのペースでギリギリになるように設定されています。 ただ、複雑な計算式を解いたりする必要もなく、基本的には数秒でわかるか全くわからないかの2択がほとんどになることもあって時間には余裕が持てると思います。

参考までに私の場合はだいたい60分ぐらいで一通り回答し終えました。あとはフラグをつけたところを再考したり、もう一度全体を見直したりしてゆっくり時間を使ってもトータル100分ぐらいでした。時間のことを考えずに問題に集中すべきです。

(余談)試験中にトラブルがあっても乱されないように

AWS認定試験は特別な端末を使って試験を行います。専用のカメラで常に監視されています。

私が実際に経験したのは、画面がフリーズして端末が自動的に再起動されてしまうことが1度の試験で5回ぐらいあったことでした。
最初は「どうしよう・・」って焦りますが、カメラに向かって手を挙げたりアピールすることで再起動してくれてるようです。

「まぁよくあること」と割り切るしかないです。先に書きましたが、試験時間はそんなに気にしなくても良いですし。

あとは、テストセンターによっては他の試験者も同じ部屋にいることがあると思いますが、 他の人が普通のPCで試験を受けている中、1人カメラに向かって手を挙げたりしないといけない状況になることもあるので、羞恥心は捨て去らないとだめですね。

最後に(+証拠)

今回はAWS認定ソリューションアーキテクトアソシエイト試験について、自分が書ける範囲でやったら良いと思うことを書きました。

この記事を見てくれた全ての人が合格することを祈っております。

とにかく、ユースケースが大事です!頑張ってください。

f:id:tatsuyashi:20190409011251p:plain:w500

筋トレログ2019 (2/9〜2/15)

f:id:tatsuyashi:20190311014307p:plain:w300

2019年2月9日(土)〜2月15日(金)の筋トレログを報告します。

場所 レーニング内容
2019年2月9日(土) - 休養
2019年2月10日(日) - 休養
2019年2月11日(月) ジム ベンチプレス:10.0kg×3セット、20.0kg×2セット
スミスマシン(インクライン):0kg×4セット
ラットプルダウン:15.0kg×3セット
ディップス:4セット
ダンベルカール:3.0kg×4セット
サイドレイズ:3.0kg×10セット
2019年2月12日(火) 自宅 スタンディングカーフレイズ:3セット
スクワット:3セット
2019年2月13日(水) - 休養
2019年2月14日(木) 自宅 プランク:2セット
サイドプランク:4セット
2019年2月15日(金) 自宅 腕立て伏せ:8セット

この週は連休に予定が入っていたので、初めて土日ともにトレーニングなしとなりました。
こうなると実際相当痛いのですが、間にちょこちょこ自宅トレを挟めているので、そこまで大きなトレーニング不足にならずに済んでいると思います。

今回のように予定があってジムに行けないっていうことは今後も十分ありえますし、 旅行などで長期間外出することもありえるので、自宅トレや自重トレのバリエーションは増やしていかないといけないなと感じています。

「忙しいからジムに行けなくてトレーニングできなかった」

っていう言い訳から卒業して、

「忙しくてジムに行けてないけど、しっかりトレーニングできてるよ!」

って言えるようになりたいですね。

2019年に取り組んでいる筋トレはこちら↓

tatsuyashi.hatenablog.com

Coderを使ってブラウザ上でAngularアプリケーションを開発してみる

f:id:tatsuyashi:20190304124442p:plain:w500

先日、こんなブログを見つけました。

qiita.com

CoderというVisual Studio Codeをブラウザ上で使えるサービスがあるそうです!(情報ありがとうございます!)

coder.com

私はメインPCがデスクトップでサブPCにChromebookを使っているのですが、Chromebookを使って開発ができると便利だなぁと思っていたのでこれは非常に朗報でした。

※一応、USBにUbuntuを入れてChromebookから使えるようにしていますが、Chromebook自体がスペックを抑えめにされているのでローカル開発にはあまり向いていません。

今回はCoder上でAngularのアプリケーションを1から作ってローカルで動作確認まで実施しましたので手順を紹介したいと思います。

プロジェクト作成

sample-angularというプロジェクトを作ってみます。

f:id:tatsuyashi:20190304111554p:plain:w500

これでプロジェクトができます。

Node.jsをマウント

デフォルトではNode.jsは入っていなかったので、Node.jsを入れてnpmを使えるようにします。

VS Codeの画面が開いたら、[Ctrl + Shift + P]でコマンドパレットを開き、「mount」と入力しEnterを押します。

f:id:tatsuyashi:20190304112158p:plain:w500

すると、マウント可能な言語とバージョンの一覧が表示されるのでNode.jsの最新版を選択します。

f:id:tatsuyashi:20190304112359p:plain:w400

f:id:tatsuyashi:20190304112503p:plain:w400

Node.jsが使えるようになります。

yarnのインストール

yarnを使いたい方は先ほどのブログにやり方が載っていますので参考にしてみてください。

記載の通りコマンドを打つと問題なくyarnがインストールできます。

Angular CLIのインストール

Angularを開発するならまずはAngular CLIが必要です。

ターミナルを[Ctrl + `]で開き、

npmの場合は

npm install -g @angular/cli

yarnの場合は

yarn global add @angular/cli

Angularプロジェクト作成

(小ネタ)単純にng newコマンドだけでも良いですが、Coder上にプロジェクトフォルダを切ってしまっているので、ここにAngularプロジェクトを展開するようにします。

ng new sample-angular --directory ./ --skipGit true

--directory ./と書くことで、カレントディレクトリ上にAngularプロジェクトが展開されるようになります。

開発サーバー起動

Angularのプロジェクトが作成できたので、開発サーバーを起動してローカルから繋いでみたいと思います。

通常のng serveではさすがにローカルから繋げられないので以下のようにして起動します。

ng serve --host 0.0.0.0 --port 3000 --disableHostCheck true

ホストを0.0.0.0、ポートを3000で起動します。
ポートは他に80や8080などいくつか用意されていますが、おなじみの4200がなさそうだったのでWebpackでよく使う3000にしました。
また、それだけだとページを表示したときに「Invalid Host Header」とエラーが表示されてしまいますので、--disableHostCheck trueをつけています。

起動中など、重い処理が動いてCPUやメモリを多く消費すると右下に「Fast Time」を勧めるメッセージが表示されます。

f:id:tatsuyashi:20190304120003p:plain:w400

Fast Timeは一時的にコンテナのスペックを大幅に上げることができる機能で、無料プランであっても5時間までは使えるそうです。

今回はFast Timeを使わずにいこうと思います。

サーバーが起動したら、左側の[CDR.co]アイコンをクリックします。
すると、現在起動中のサーバーが表示されます。

f:id:tatsuyashi:20190304115738p:plain:w400

このURLをクリックすると、ブラウザでURLを開きます。

f:id:tatsuyashi:20190304120656p:plain:w500

ページが正しく表示されました。

LiveReloadも正しく動くので、Coder側でコード変更するとサーバーが再起動してブラウザがリロードされます。

感想

使ってみた感想をいくつかあげてみます。

【良かった点】

  • 導入が非常に簡単
  • コンテナベースなので、ミスっても捨てたりするのが簡単

【気になった点】

  • 画面の動作1つ1つが少しもっさりしている(Containerへの切り替えやVSCodeでファイルを開いた際)
  • プロジェクトを削除してもソースが残っている? →VSCodeで開いたときのプロジェクトが、削除した方のプロジェクトが選択されている

今回はAngularで試してみましたが、この調子だとReactやVueでも全く問題なく開発ができそうですね。
いくつか気になる点はありますが、Chromebookでもストレスなく開発できるのでこれから作業が捗りそうです。

こういうオンラインのIDEがこれからどんどん増えてくれるとありがたいですね。

ReactNative+ExpoでAndroid端末へプッシュ通知を送る その②〜AWS Lambdaを使ってプッシュ通知〜

Expoを使用して開発するReactNativeアプリから各端末へプッシュ通知を送る仕組みを開発しています。

前回の記事では、Expoを使ったプッシュ通知に必要なExpoプッシュトークンを取得するところまで書きました。↓

tatsuyashi.hatenablog.com

今回は、取得したプッシュトークンを使用して実際にプッシュ通知を送る方法を記載します。
なお、バックエンドは全てAWSにしているため、今回はAWS Lambdaを使ってプッシュ通知を送ってみました。

プッシュ通知の流れ

プッシュ通知を送るまでの流れは下記の3ステップです。

AWS Lambda (Node.js) でプッシュ通知

Node.jsでLambdaを書いてプッシュ通知をしようと思います。

Expoからプッシュ通知を送るためのSDKが各言語向けに用意されているのでそれを使用します。 ちなみにNode.jsの他にはPythonRuby、Go、Elixir、PHPなどのSDKが有志によって用意されています。

Push Notifications - Expo Documentation

実はNode.js向けSDKGithubのREADMEのサンプルコードにほぼ答えが載ってるのでした。

github.com

上記を参考にして使ったLambdaのソースを抜粋して載せていきます。

準備

expo-server-sdkを追加します。

npm install expo-server-sdk

外部モジュールに依存するのでLambdaはインラインではなくZip形式にしたものをアップロードします。

コード

完全に公開できるものではないので、一部抜粋となりますがご了承ください。

const { Expo } = require('expo-server-sdk');

// Create a new Expo SDK client
let expo = new Expo();

exports.handler = async (event, context) => {
    // 通知メッセージを取得
    const messages = await getMessages(event);
    
    // 通知する
    const tickets = await sendPushNotifications(messages);

    // 通知結果を保存する(必要に応じて)
    await saveTickets(tickets);
}

const getMessages = async (event) => {
    // ここに通知するメッセージを取得する処理を書く
    ...
    
    return [
        // 1つ1つのメッセージは以下の形式で
        {
                to: pushToken, // Expoプッシュトークン
                sound: 'default',  // 通知時の音を鳴らすかどうかの設定
                title: title,  // 通知タイトル
                body: body  // 通知本文
            }
    ]
}

const sendPushNotifications = async (messages) => {
    // The Expo push notification service accepts batches of notifications so
    // that you don't need to send 1000 requests to send 1000 notifications. We
    // recommend you batch your notifications to reduce the number of requests
    // and to compress them (notifications with similar content will get
    // compressed).
    let chunks = expo.chunkPushNotifications(messages);
    let tickets = [];

    // Send the chunks to the Expo push notification service. There are
    // different strategies you could use. A simple one is to send one chunk at a
    // time, which nicely spreads the load out over time:
    for (let chunk of chunks) {
        try {
            let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
            console.log(ticketChunk);
            tickets.push(...ticketChunk);
            // NOTE: If a ticket contains an error code in ticket.details.error, you
            // must handle it appropriately. The error codes are listed in the Expo
            // documentation:
            // https://docs.expo.io/versions/latest/guides/push-notifications#response-format
        } catch (error) {
            console.error(error);
        }
    }
    return tickets;
}

const saveTickets = async (tickets) => {
    // ticketsをデータベースに保存するような処理
}

上記ソースコードで言うと、sendPushNotificationsメソッドがプッシュ通知を送るメイン処理となります。

その前にgetMessagesメソッドでプッシュ通知の対象データを返してあげます。 1つ1つのメッセージに設定できる項目は下記に載っています。

Push Notifications - Expo Documentation

最後にsaveTicketsメソッドでプッシュ通知の結果をデータベースに保存します。
この処理を行っている理由ですが、SDKのREADMEには以下のコードも併記されています。

// Later, after the Expo push notification service has delivered the
// notifications to Apple or Google (usually quickly, but allow the the service
// up to 30 minutes when under load), a "receipt" for each notification is
// created. The receipts will be available for at least a day; stale receipts
// are deleted.
//
// The ID of each receipt is sent back in the response "ticket" for each
// notification. In summary, sending a notification produces a ticket, which
// contains a receipt ID you later use to get the receipt.
//
// The receipts may contain error codes to which you must respond. In
// particular, Apple or Google may block apps that continue to send
// notifications to devices that have blocked notifications or have uninstalled
// your app. Expo does not control this policy and sends back the feedback from
// Apple and Google so you can handle it appropriately.
let receiptIds = [];
for (let ticket of tickets) {
  // NOTE: Not all tickets have IDs; for example, tickets for notifications
  // that could not be enqueued will have error information and no receipt ID.
  if (ticket.id) {
    receiptIds.push(ticket.id);
  }
}

let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);
(async () => {
  // Like sending notifications, there are different strategies you could use
  // to retrieve batches of receipts from the Expo service.
  for (let chunk of receiptIdChunks) {
    try {
      let receipts = await expo.getPushNotificationReceiptsAsync(chunk);
      console.log(receipts);

      // The receipts specify whether Apple or Google successfully received the
      // notification and information about an error, if one occurred.
      for (let receipt of receipts) {
        if (receipt.status === 'ok') {
          continue;
        } else if (receipt.status === 'error') {
          console.error(`There was an error sending a notification: ${receipt.message}`);
          if (receipt.details && receipt.details.error) {
            // The error codes are listed in the Expo documentation:
            // https://docs.expo.io/versions/latest/guides/push-notifications#response-format
            // You must handle the errors appropriately.
            console.error(`The error code is ${receipt.details.error}`);
          }
        }
      }
    } catch (error) {
      console.error(error);
    }
  }
})();

プッシュ通知でエラーになった場合はなんらかの対応をしないといけないらしく、そのために上記のようなreceiptの取得処理を行わないといけないようです。

ただ、処理を行うにしても今回のLambdaとは別のLambdaにすべきで、プッシュ通知そのものとは切り離すべきですね。

まとめ

以上のようにして、Lambdaを使ってExpo経由でプッシュ通知を送ることができました。

今回のLambdaはDynamoDB StreamsをトリガーとするLambdaを書いていますが、プッシュ通知を送るケースとしては他にも

  • Kinesisを使ったリアルタイムストリーム処理
  • CloudWatchの定時実行イベント

などのトリガーでLambdaを動かすことがあると思いますので、そういったケースで今回のコードが参考になれば幸いです。

IFTTT入門〜【超簡単】3分でGoogle HomeとGoogleスプレッドシートを連携してみる〜

f:id:tatsuyashi:20190226005821j:plain:w300

Webサービスを簡単に繋ぐことができるIFTTT(イフト)というサービスをご存知でしょうか?

世の中には様々なWebサービスが存在していますが、それらを組み合わせることで人々の「やりたいこと」を実現するのがIFTTTです。

今回は初めてIFTTTを使ってみるということで、手始めにGoogle Home (Google Assistant)とGoogleスプレッドシートを連携させてみましたので紹介したいと思います。

所要時間はアカウント登録から連携完了まで約3分です。

【今回のゴール】
以下のような連携をするのを今回のゴールとします。

  1. Google Home (Google Assistant) で「OK Google、今日の運勢は○位でした」と話す
  2. Google Home (Google Assistant) が「今日は運勢は○位だったのですね」と返事する
  3. 自分のGoogleドライブにあるスプレッドシートに今日の順位を記録する

IFTTTって?

冒頭でも書きましたが、「2つのWebサービスを繋ぐ」のがIFTTTです。

ifttt.com

IF This Then Thatを略してIFTTT(イフト)と呼ばれていて、思想としては非常にシンプルです。

IF A Then B
Aのとき、Bを行う。)

このAトリガーBアクションと言います。

このWebサービスの組み合わせはアプレットと呼ばれていて、世界中のユーザーが作った様々なレシピが公開されています!

ですので、自分がやりたいことがあればまずはレシピを探してみるのが良いと思います。

ちなみにIFTTTで連携可能なサービスはざっと数百種類はありそうなので、主要なサービスは網羅されていると考えて良いです。

アカウント登録

まずはアカウント登録をします。

公式サイトへアクセスして登録してください。

GoogleFacebookで登録ができるので、私はGoogleで登録しました。

アプレット作成

アカウントを作成したら画面の左上にある「My Applet」をクリックします。

f:id:tatsuyashi:20190226015439p:plain:w500

「New Applet」をクリックします。

f:id:tatsuyashi:20190226015654p:plain:w500

IF This の設定 (Google Assistant)

まずはGoogle Assistantへの音声入力をトリガーとする設定を行います。

「[+]this」をクリックします。

f:id:tatsuyashi:20190226020111p:plain:w500

サービスを検索し、「Google Assistant」を選択します。

f:id:tatsuyashi:20190226020604p:plain:w500

「Connect」をクリックすると、Googleアカウントの連携を求められるので許可します。

f:id:tatsuyashi:20190226020901p:plain:w500

Google Assistant用のトリガーとしては4種類用意されています。

・Say a simple phrase (変数なし)
・Say a phrase with a number (数字の変数が1つ)
・Say a phrase with a text ingredient (テキストの変数が1つ)
・Say a phrase with a number and a text ingredient (数字とテキストの2つを変数とする)

今回のように数字を変数にする場合、Say a phrase with a numberとSay a phrase with a text ingredient がどう違うのかがよくわからないですが、
数字が来るということが決まっている前者だと認識がよくなるんでしょうかね?

ということで、今回は「Say a phrase with a number」を選択します。

f:id:tatsuyashi:20190226021853p:plain:w500

Google Assistantに認識させるフレーズを入力します。
数字の変数が入るところは「#」を入力します。

※「#」の前後に半角スペースが必要です

f:id:tatsuyashi:20190226023358p:plain:w500

フレーズは最大3つまで登録できます。

f:id:tatsuyashi:20190226023438p:plain:w500

Google Assistantからの返事を入力します。ここでも「#」が使えます。

f:id:tatsuyashi:20190226023547p:plain:w500

最後に言語を「Japanese」に変更して「Create Trigger」をクリックします。

f:id:tatsuyashi:20190226023126p:plain:w500

これでトリガーの設定は完了です。

Then Thatの設定 (Googleスプレッドシート)

次にスプレッドシートに書き込むアクションの設定を行います。

「[+] that」をクリックします。

f:id:tatsuyashi:20190226023819p:plain:w500

サービスを検索し、「Google Sheets」を選択します。

f:id:tatsuyashi:20190226024004p:plain:w500

「Connect」をクリックすると、Googleアカウントの連携を求められるので許可します。

f:id:tatsuyashi:20190226024259p:plain:w500

Google スプレッドシートのアクションとしては以下の2つが用意されています。

  • Add row to spreadsheet

  • Update cell in spreadsheet

今回は記録を新しい行として追加したいので「Add row to spreadsheet」を選択します。

f:id:tatsuyashi:20190226024620p:plain:w500

スプレッドシートに書く内容を設定します。

ファイル名を設定します。一応ここでも変数が使えるみたいです。

f:id:tatsuyashi:20190226024916p:plain:w500

行に書く内容を設定します。
CreatedAtはタイムスタンプでNumberFieldは「変数」にあたります。

f:id:tatsuyashi:20190226025100p:plain:w500

Googleドライブのフォルダを指定して「Create action」をクリックします。

f:id:tatsuyashi:20190226025217p:plain:w500

最後に内容を確認して、「Finish」をクリックします。

「Recieve notifications when the Applet runs」を選択しておくと、アプレット実行時に通知を受け取れます。

f:id:tatsuyashi:20190226025509p:plain:w500

これでアプレット作成が完了しました!

f:id:tatsuyashi:20190226025739p:plain

さっそく試してみる

Google HomeまたはスマートフォンGoogle Assistantに話しかけてみた結果がこちらです。

f:id:tatsuyashi:20190226030556p:plain:w400

IFTTTで設定した通りの返事をしてくれていますね!

次にGoogleドライブですが、Googleフォルダが作成されて「占い記録」というファイルが作成されています。

f:id:tatsuyashi:20190226030800p:plain:w400

ファイルを開くと、

f:id:tatsuyashi:20190226030845p:plain:w400

こちらもIFTTTで設定した通りに記録されていますね!

まとめと感想

いかがだったでしょうか?

はっきり言って超絶簡単です。IFTTTはスマホアプリも用意されているので、今回のような簡単な連携であればスマホで簡単に作成できます。

IFTTTは1つのトリガーで1つのアクションしかできないが故に複雑なことはできませんが、シンプルにサービスを繋ぐだけであれば非常に強力です。

また今回のようにGoogle HomeAmazon Echoなどのスマートスピーカースマートホームとの相性も良いと思うので、アイデア次第で生活を非常に便利にできるのじゃないかなと思います。

ちなみに、IFTTTではWebhooksが使えるので自作のAPIとも連携できたりします。そうなると可能性は無限に広がるのですが、またそれはやってみたときに書きたいと思います。