QtアプリからIFTTT Webhooksのトリガを実行する
1. 初めに
Qtアプリ(Qt5/C++)からIFTTTのWebhooksを叩いて、スマホにプッシュ通知するサンプルを紹介します。
IFTTTのWebhooksに関して、参考にしたサイトはこちらです。
クライアントであるQtアプリからHTTP POSTを実行するサンプルを作ってみたくて作成しました。
ソースコードはgithubに置いてあります。
IFTTTに関しては、元ネタ記事をほぼ同じですが、1つの記事に完結していたほうが読みやすいと思ったので、キャプチャをペタペタ貼って説明しています。
<-- 2018/05/07 追記 start -->
Qtのサンプルに関して
投稿して1日経ち、やはりvalue1()などにデフォルト実装がないのはおかしい(value1だけ設定してvalue2やvalue3を使用しない場合を考慮できていない)為、デフォルト実装を入れるよう実装を変えました。
混乱させてしまい申し訳ありません。
<-- 2018/05/07 追記 end -->
1.1. 動作確認環境
- Qt Version 5.10.1
- Qtアプリの動作環境:Windows10
- スマホ(SO-02J(OSはAndroid8.0.0))
- IFTTTアプリ(Android版)
2. 動作
IFTTTやプログラムの説明をする前に、動作の説明をします。
Qtアプリを実行すると、
という画面が立ち上がります。
このアプリの「POST Request」ボタンを押下すると、
が表示され、その後、POSTリクエストが正常に終了すると、
が表示されます。
スマホ側では、Notificationで、
のように通知されます。
「hello」というイベントが発生し、Value1、Value2、Value3にそれぞれ、test1、test2、test3というパラメータが設定されているのが確認できます。
3. IFTTTの設定
ブラウザを開きます。(Internet ExplorerはNGのようです。本記事の操作はGoogle Chromeを使用しています)
IFTTTにSign Inして、アプレットの作成を行います。
3.1. アプレット作成
メニューの「My Applets」から、「New Applet」(スマホアプリだと「+」ボタン)を押下します。
すると、下記のような画面が表示されます。
3.1.1. トリガ(this)
を選択します。
すると、イベント名を入力する画面になりますので、入力します。
ここでは、元ネタ記事と同じように「hello」とします。
入力後、「Create trigger」を押下します。
3.1.2. アクション(that)
thatを選択後、検索バーで「noti」を入力し、
を選択します。
次に、
を選択します。
次に、
の画面で、Messageを下記のように入力します。
使用できるパラメータは、「Add ingredient」ボタンを押下して入力するのが確実です。
入力後「Create action」ボタンを押下します。
その後、「Finish」ボタンを押下すればアプレット作成完了です。
3.2. IFTTT webhooksの動作確認
作成したアプレットを選択し、左上のマークを押下します。
次に、右上の「Documentation」ボタンを押下します。
すると、次の表示されます。
この画面は、どうやってWeb APIを叩いてよいのかの全てが説明され、試しに動作確認までできる、かなりわかりやすいページです。
Webhooks APIのURLに設定する要素は下記の5つです。
- イベント名
- アクセスKey
- value1
- value2
- value3
※IFTTTのアプレット作成画面だとvalue1はValue1と表示されていますが、URLのパラメータとしては全部小文字の名前になります。
Your Key isのところにアクセスキーが記述されていますので、これをメモっておきます。(Qtのプログラムで使用します。)
ついでに、アプレットの動作確認をします。
赤字の部分に各パラメータに設定したい値を入力し、「Test It」ボタンを押下します。
すると、Qtアプリの代わりに、トリガが発生します。
アクションが実行されたことをスマホで確認したら、ブラウザ上での操作は終了です。
4. Qtアプリの実装
IFTTTにアクセスするクラスをして作成したのは、
- IftttAccessManagerクラス
- IftttTestクラス(IftttAccessManagerクラスの子クラス)
の2つです。
4.1. IftttAccessManagerクラス
IFTTT Webhooksにアクセスする仕組みを定義したクラスです。
IftttAccessManagerクラス自身では、下記コードのように、QNetworkAccessManagerを使用してPOSTしています。
プロジェクトファイルに
QT += network
の設定をすれば使用できるようになります。
IftttAccessManager::IftttAccessManager(QObject *parent) : QObject(parent)
{
m_networkManager = new QNetworkAccessManager(this);
}
void IftttAccessManager::requestPost()
{
QUrl url("https://maker.ifttt.com/trigger/" + eventName()
+ "/with/key/" + webhooksKey());
QUrlQuery postData;
QString value1Str = value1();
if (!value1Str.isEmpty()) {
postData.addQueryItem("value1", value1Str);
}
QString value2Str = value2();
if (!value2Str.isEmpty()) {
postData.addQueryItem("value2", value2Str);
}
QString value3Str = value3();
if (!value3Str.isEmpty()) {
postData.addQueryItem("value3", value3Str);
}
url.setQuery(postData);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
m_networkReply = m_networkManager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
connect(m_networkReply, &QNetworkReply::finished, this,
[=](){
if (m_networkReply->error()) {
emit postFinished((m_networkReply->errorString()));
} else {
emit postFinished("POST finished");
}
m_networkReply->deleteLater();
});
カスタマイズできる5つのパラメータについては、デザインパターンのTemplate Methodパターンで、子クラスに設定させます。
protected:
virtual QString value1();
virtual QString value2();
virtual QString value3();
virtual QString webhooksKey() = 0;
virtual QString eventName() = 0;
※Template Methodパターンについて補足
Template Methodパターンでは子クラスに設定させる要素を必ずしもpure virtualにしなければならないわけではありません。virtualだけ付けて( =0 を付けずに)、親クラスでデフォルト設定を記述しておく場合もあります。今回の例ではvalue1()関数などがそれに当たります。(value1Str.isEmpty()で判定する為にデフォルト実装で空文字を返します)
Template Methodパターンは、必ずpure virtualにしなければならないと勘違いしている人(というかソースコード)を見かけたことがあるので、もしそういう人が近くにいたら教えてあげてほしいです。
pure virtual関数をOverrideした子クラスの関数の中身が全て同じだったという悲しいコードはあまり見たくないです。。。
4.2. IftttTestクラス
今回動作確認用のパラメータを記述したクラスです。
webhooksKey()は、3.2.項でメモっておいたKeyを設定してください。
QString IftttTest::value1()
{
return "test1";
}
QString IftttTest::value2()
{
return "test2";
}
QString IftttTest::value3()
{
return "test3";
}
QString IftttTest::webhooksKey()
{
return "Your Key";
}
QString IftttTest::eventName()
{
return "hello";
}
4.3. コードを記述している時に気づいたこと
QNetworkAccessManager周りはQt4→Qt5に移行している内に仕様が変わったようです。
2点気づいたことがあります。
1つ目は、パラメータを設定する為のQUrl::addQueryItem()がDuplicatedになっており、Qt5.10.1ではビルドすら通らないことです。
代わりに、QUrlQuery::addQueryItem()を使用するようです。
詳しくは、Stack Overflowの記事を参照してください。
2つ目は、エラーハンドリングについてです。
最初、QNetworkAccessManager::finish()シグナルをキャッチし、引数のQUrlQuery *replyから
reply->error()でエラーかどうかを判断するつもりだったのですが、判断できませんでした。
「https」を「htps」に変更してエラー処理の動作確認を行いましたが、No Errorが返ってきます。
ここを見る限りできそうだったのですが、仕様が変わったのでしょうか?
そこで、本サンプルのようにpost()関数の返り値であるQNetworkReplyから判断します。
このpost()関数の返り値で返ってきたQNetworkReplyは自分でdeleteする必要がある為、エラーかどうかを確認後、QNetworkReply::deleteLater()を呼んでいます。
5. 最後に
いかがでしたでしょうか。
QNetworkAccessManagerを使用すれば、わりと簡単にクライアント側のPOSTのコードを書け、IFTTTを使用すれば、サーバ側の動作も簡単に実装することができることがわかりました。
ネットワークプログラムというと、どうしても(特にクライアントサイドのプログラムを書いている人には)ハードルが高いというイメージがありますが、作ってみればそう難しいことではないと思います。
Gitに登録してから、
- 可変パラメータは全て画面で設定できるようにしておけば、もっとかっこいいサンプルになったとか
よく考えれば、value1、value2、value3はpure virtualにしなくてよくね?ということに気づいたりとか・・・
まあ、この辺りで勘弁してくださいm(_ _"m)
読者様の参考になれば幸いです。
Author And Source
この問題について(QtアプリからIFTTT Webhooksのトリガを実行する), 我々は、より多くの情報をここで見つけました https://qiita.com/argama147/items/5ee8e8c82a68a1b20991著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .