論文紹介:DiffNILM: A Novel Framework for Non-Intrusive Load Monitoring Based on the Conditional Diffusion Model

NILM(Non-Intrusive Load Monitoring)の論文紹介 3回目です。 今回は2023年に発表された論文の1つを紹介します。

www.mdpi.com

3行で説明する

  • NILMの分野で初めてDiffusion modelを使った
  • 全体電力と埋込み時間情報を入力とする条件付きDiffusionモデル
  • 計算量には目をつぶるが既存手法を上回る結果を達成した

アプローチ

拡散モデル(Diffusion model)は 以下の図のように 拡散過程 と 逆拡散過程 から成り、逆拡散過程によってランダムノイズからデータを生成します。

DiffNILM論文よりFigure1

NILMは分離のタスクなので

  • 入力:家全体の消費電力の系列
  • 出力:(そのうちの)ある家電の消費電力系列

となります。

単純に拡散モデルを適用してもランダムに電力データが出力されるだけとなり目的には合いません

条件付き拡散モデル

そこで条件付きの拡散モデルの出番です。 DALL・Eなどの画像生成AIではプロンプトがそれ(条件)に当たり、条件に応じた生成データを出力してくれます。

図中のConditional inputsとなるところが条件入力となり、

  • Aggregated power data: 家の全体電力の系列
  • Embedded temporal features: 時間系列の埋め込み情報

が入力されます。

DiffNILM論文よりFigure4

これにより、家全体の消費電力情報と時間情報に応じて各家電の消費電力データ(Diffused appliance-level power data)を生成できるようになります

(拡散モデルなのでモデル自体は真の家電消費電力データに近づくように取り除くべきノイズ成分 $ \epsilon_{\theta} $ を出力します)

時間情報埋め込み

家電は季節や時間帯によって使われやすい/使われにくいが変わってくるので時間情報を埋め込みとして入力するのは Make sense です

DiffNILM論文よりFigure3

  • Month of year:何月
  • Hour of day: 何時
  • Day of week: 何曜日

の3次元情報を ~0.5~+0.5 の範囲で埋め込みます

アーキテクチャ

推定ノイズ成分 $ \epsilon_{\theta} $ を出力するネットワークです

DiffNILM論文よりFigure5

  • $ X_\overline{a} $:ノイズ含む家電消費電力系列
  • $ \sqrt{\overline{a}} $:ノイズレベル
  • $ X_{aggre} $ : 家全体の消費電力系列
  • $ X_{time} $:時間埋め込み情報

実験情報では 残差レイヤーは10個 とのことで大きいネットワークです。

活性化関数としては SiLu (Sigmoid Linear Unit)が使われています。

学習とサンプリングの手順

学習フェーズ

DiffNILM論文より

実験情報では T = 1000 となっています

  1. 開始
  2. 学習データセットから家電正解電力 $ x_0 $ を取り出す
  3. 1~1000の一様分布から $ t $ をサンプリング
  4. 時刻 $ t $ でのノイズ率 $ \sqrt{\overline{\alpha}_{t}} $ 〜 $ \sqrt{\overline{\alpha}_{t-1}} $ の一様分布から ノイズ率 $ \sqrt{\overline{\alpha}} $ をサンプリング
  5. 標準正規分布から ノイズ $ \epsilon $ をサンプリング
  6. モデルで予測したノイズ成分 $ \epsilon_{\theta} $ と $ \epsilon $ の L1対数誤差 を損失関数として 逆伝搬させる
    • $ \sqrt{\overline{\alpha}} $ :ステップ4のノイズ率
    • $ x_{\overline{\alpha}} $ :正解電力 $ x_0 $ にノイズ率 $ \sqrt{\overline{\alpha}} $ に応じてノイズを付加したデータ
    • $ x_d $ : 全体電力データと時刻情報埋め込みデータ
  7. 収束するまで続ける

L1損失ではなく対数L1損失を使うほうが収束も速く、結果も良かったとのことです。

サンプリングフェーズ

DiffNILM論文より

  1. 標準正規分布からランダムノイズ $ x_T $ をサンプリング
  2. $ T_{infer} $ ステップ分、以降の処理(3. ~ 6.)を繰り返す
  3. 標準正規分布からランダムノイズ $ z $ をサンプリング
  4. ノイズスケジューラから時刻 $ t $ における $ \overline{\beta}_{t} (= 分散)$ を計算
  5. モデルにノイズ成分 $ \epsilon_{\theta} $ を予測させ、$ x_t $ から引き算する(→時刻 $ t $ での $ x_t $ の平均値 $ \mu_{\theta} $)
  6. 時刻 $ t $ での平均値 $ \mu_{\theta} $ に ステップ3のランダムノイズ $ z $ に分散をかけたものを加算し、$ x_{t-1} $ とする
  7. $ t = 0 $ になるまで繰り返す
  8. $ t = 0 $ 時点での 生成電力データ $ x_0 $ (=家電の予測電力データ)を返す

実験情報からは $ T_{infer} = 8 $ ということで たった8ステップで生成できるのは驚きました

fast sampling([2106.00132] On Fast Sampling of Diffusion Probabilistic Models)という手法らしいです。

評価

データセット

データセットデファクトとも言える

  • REDD
    • 6家庭、約4ヶ月分のデータ
  • UKDALE
    • House1:3年分のデータ
    • House2~5:数ヶ月分のデータ

が使われています

評価指標

  • 分類
    • Accuracy
    • F1-score
  • 回帰
    • MAE
    • MRE (Mean Relative Error)

DiffNILM論文より

MRE は分母が 正解値と予測値のmaxとなっており、正解値を分母とするMAPEとは若干違っています

MAPEでは正解値が小さいときに大きく外すと分母が小さいため大きなペナルティが課されますが、MREではそれが緩和されています。

正解値 予測値 誤差 MAPE MRE
100 1000 900 9.0 0.9
1000 100 900 0.9 0.9

リファレンスモデル

リファレンスモデルは以下の4つです

cGANの論文はIEEEの有料論文となっていて購入しない限り読めないですが ICASSPでの発表スライド(SEQUENCE-TO-SUBSEQUENCE LEARNING WITH CONDITIONAL GAN FOR POWER DISAGGREGATION | SigPort)は閲覧可能です

評価結果

<REDDでの評価結果>

DiffNILM論文よりTable3

提案手法であるDiffNILMが分類タスク(F1スコア)でも回帰タスク(MAE、MRE)でも全体を通して良い結果になっています。

特に、電力パターンが複雑なWasher(洗濯機)、Dish washer(食洗機)において良いスコアを示しています。

<UKDALEでの評価結果>

DiffNILM論文よりTable4

REDDでの結果よりもDiffNILMの優勢さが目立つ結果になっています。

もう1つの生成モデルであるcGANもスコアがREDDに比べて改善しており、学習データ量が増えたことにより性能を発揮するようになったと考えられます。(REDDの4ヶ月に対してUKDALEは3年)

学習データが十分にないときに生成モデルを使うことは不適当であることを示唆しています

所感

計算量は膨大だと思われますが分離性能は有望そうであり、今後、計算コストの改善を期待したいです。(すぐに思いつくのは潜在拡散モデルの導入ですがどうなんだろう)

以下のような色々な細かい工夫がなされているので

  • ReLuではなく、SiLu
  • L1損失ではなく、対数L1損失
  • fastサンプリング

安定的に学習&予測させるのは大変なんだろうなぁと思いつつ、 サンプル実装が公開されたら追試してみたいところです。

GCEインスタンスに急にsshログインできなくなったときの対応

ローカルマシンを新調したら今までsshでログイン出来ていたリモートホストに突然ログインできなくなりました。

$ gcloud compute ssh REMOTE_HOST

USER@IP_ADDRESS: Permission denied (publickey).

sshに関してよくあるエラーメッセージです。

ただ、新旧マシンで .sshディレクトリやファイルの権限、鍵の中身を確認しても同一であり問題なさそうでした。

原因

no mutual signature algorithm という署名アルゴリズムのミスマッチが原因でした

調べ方

ssh時にvTオプションをつけることで原因が分かりました

$ ssh -vT -i ~/.ssh/google_compute_engine USER@REMOTE_HOST
...
...
debug1: send_pubkey_test: no mutual signature algorithm
debug1: No more authentication methods to try.
...

と、出力メッセージの中にエラーの原因が出力されてます

コマンドヘルプによると

     -T      Disable pseudo-terminal allocation.
     -v      Verbose mode.  Causes ssh to print debugging messages about its progress.  This is helpful in debugging connection, authentication, and configuration
             problems.  Multiple -v options increase the verbosity.  The maximum is 3.

とのことです。

対処方法

参考記事そのままになりますが

PubkeyAcceptedKeyTypesのオプションをつけて接続する

$ ssh -o 'PubkeyAcceptedKeyTypes +ssh-rsa' -i ~/.ssh/google_compute_engine USER@REMOTE_HOST

あるいは、 ~/.ssh/config に以下を記述

Host {REMOTE_HOST}
  HostKeyAlgorithms ssh-rsa
  PubkeyAcceptedKeyTypes ssh-rsa
  IdentityFile ~/.ssh/google_compute_engine

これで問題なく今まで通りログインできるようになりました

(参考)各マシンのsshのバージョン

# Remote Host (GCEのVM)
OpenSSH_6.7p1 Debian-5+deb8u1, OpenSSL 1.0.1k 8 Jan 2015

# Old Mac (Remote HostへのSSH OK)
OpenSSH_8.1p1, LibreSSL 2.7.3

# New Mac (Remote HostへのSSH NG)
OpenSSH_9.0p1, LibreSSL 3.3.6

バージョン乖離が大きいときは要注意ということですね

追記

後で見つけた記事、これこれによると OpenSSH 8.8 から RSA方式が使えなくなったようです。

自分の場合は同じ鍵をそのまま使いたかったので暫定的な対処をしましたが、本来は強度の強い暗号化形式で鍵を新規作成すべきでしょう

$ ssh-keygen -t ed25519

参考記事

論文紹介: SAED: self-attentive energy disaggregation

今回もNILM(Non-Intrusive Load Monitoring)論文紹介です。 前回のNeural Fourier Energy Disaggregationの論文紹介でリファレンス手法として挙げられていた論文です。

link.springer.com

2行で説明すると

  • BidirectionalGRUの代わりにシンプルなAttention機構を組み込んでみたよ
  • 軽量かつ特に汎化性能に関して良い性能を示したよ

モデルアーキテクチャ

モデルアーキテクチャは以下のようになっています

基本的には、WGRU手法の最初のBidirectional GRU層がAttention層に置き換わっただけですが 後半のBidirectional GRU層のサイズやDense層のサイズも 128 -> 64 と減少しています

<WGRUのアーキテクチャNFED論文より引用)

軽量を謳っているように、モデルのパラメータサイズは圧倒的にリファレンスモデルと比べて小さくなっています。

Attention層を導入することにより性能を落とさず全結合層のサイズを小さくできたためと解釈するのが良さそうです。

Additive or Dot

Attention層は 論文の図中にもあるようにシンプルなもので Additive と Dot の2種類のAttentionが使われています

それぞれ

に対応しています。

それぞれのkeras実装はこちらになります

Luongの論文ではconcat含む以下の3種類のやり方が示されているのですがこのうちの dot が Luongスタイルということみたいです。

(https://arxiv.org/pdf/1508.04025.pdf より)

dot手法のSAED-dotのほうが高速であり、以下の表を見ると性能としてもSAED-dotのほうがadditive手法のSAED-addのほうより若干優勢と読み取れます。

性能評価

データセット

データセットは UK-DALEと REDD、REFITが使われています。

DW(食洗機)、FZ(冷蔵庫)、KT(ケトル)、MW(電子レンジ)、WM(洗濯機)については、

Category1 Category2 Category3 Category4
Train UK-DALE 1家庭
UK-DALE 1家庭
UK-DALE 2~4家庭 UK-DALE 2~3家庭
Test UK-DALE 1家庭(trainと同じ) UK-DALE 2~4家庭(trainと別) UK-DALE 1家庭(trainと別) REDDの4~5家庭

TVとPCに関しては、

Category1 Category2 Category3 Category4
Train REFIT 1家庭
REFIT 1家庭
REFIT 2家庭 REFIT 2家庭
Test REFIT 1家庭(trainと同じ) REFIT 1家庭(trainと別) REFIT 2家庭(trainと別) UK-DALEの1~2家庭

という学習/テスト条件になっています

Category1は汎化性能を確認するための比較条件となり、基本的にはCategory2~4の結果に注目すべきでしょう

評価指標

F1スコア、MAEといった馴染みのある指標に加えて 汎化性能を示すための指標としてAUH、EUH、MGLが使われています。

  • AUH: Accuracy on Unseen Houses
  • EUH: Error on Unseen Houses
  • MGL: Mean Generalization Loss

AUHとEUHの定義はこちら

学習に使ってない家庭の平均F1スコア、平均MAEということであり、素直に理解できます。AccuracyとなってますがF1スコアの平均です。

MGLの定義はこちら

F1スコアベースでもMAEベースでも 直感的には、

  • seen家庭スコア > unseen家庭スコア: 正の値
  • seen家庭スコア = unseen家庭スコア: 0
  • seen家庭スコア < unseen家庭スコア:負の値 (あり得る??)

となります

つまり、0や負の値に近づくなどマイナスも含めて数値が小さくなればなるほど汎化性能が良いということを表します。

リファレンスモデル

Seq2Point NFED論文より引用)

色々なNILM論文で引用されるSeq2PointやWGRUが比較対象となっており、基本的には信頼できそうです

定量評価結果

論文中はすべて表ベースになっていて比較がやりにくく分かりにくいのでグラフにしてみました

Time/ep

まず、一番わかり易い Time/ep(1エポックあたりの学習時間)から

Time/ep

WGRUが断トツに遅くなっており、Seq2PointはSAED-dotはほぼ同等レベル(若干SAED-dotのほうがより速い)、SAED-addはこれら2つに比べるとやや遅い という結果になっています。

F1スコア

F1

category1~2ではWGRUであったりSeq2Pointが若干良さそうですが category3~4ではSAEDの2手法がやや良さそうに見えます。

MAE

MAE

F1スコアと同様の結果(優劣)になってます

(参考)家電別 F1スコア

F1(家電別)

(参考)家電別 MAE

MAE(家電別)

感想

実験結果からは SAEDはcategory3~4といったところで相対的に成績が良く、汎化性能について優れているという主張でした。

アテンション機構の強力さだったりやパラメータ数の少なさから良い汎化性能を示すという流れは理解できますが 同じ家庭の学習/評価のcategory1より学習家庭と異なる家庭を評価したcategory2のほうがスコアが良かったりする箇所が至るところであり(家電別 F1スコアのグラフでよく分かる)、結果に関して??な所が残ります。

単にリファレンス手法が過学習気味になっている可能性も頭に入れておきたいです。

引用数も17件と多くなく、他の著者の論文で本手法がリファレンスとして登場するのか注目したい所です

Mac (Apple Silicon) で gcsfuse を使う方法

意外と参考記事がなかったのでメモを残します。 インストールまではスムーズですがその後のセキュリティ絡みのところが面倒でした。

前提

手順

1. Macfuseのインストール

$ brew install --cask macfuse

過去記事では macfuse ではなくosxfuse をインストールするものもありますが osxfuse has been succeeded by macfuse as of version 4.0.0. ということのようなので macfuseをインストールします

2. Goのインストール

$ brew install gcsfuse では、

gcsfuse: Linux is required for this software. libfuse: Linux is required for this software. Error: gcsfuse: Unsatisfied requirements failed this build.

となり、Apple SiliconのMacへは直接インストールできないのでGoをインストールしてビルドします。

$ brew install go

インストールできたらバージョン確認できるはずです

$  go version
go version go1.22.0 darwin/arm64

3. gcsfuseのインストール

$ go install github.com/googlecloudplatform/gcsfuse@master

でインストールはすんなり完了

インストールできたら .zshrc でパスを追加します

export PATH=$HOME/go/bin:$PATH

参考記事に書かれている

GO111MODULE=auto go get -u github.com/googlecloudplatform/gcsfuse

だと、

go: go.mod file not found in current directory or any parent directory.
    'go get' is no longer supported outside a module.
    To build and install a command, use 'go install' with a version,
    like 'go install example.com/cmd@latest'

となっちゃいます。古い情報になってしまっています

ちなみに、Go関連の環境変数は以下で確認できます。インストール後のデフォルト設定を変更する必要はありませんでした

$ go env
GOPATH='/Users/xxx/go'
GOROOT='/opt/homebrew/Cellar/go/1.22.0/libexec'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.0/libexec/pkg/tool/darwin_arm64'

4. Cloud Storage への Cloud Storage FUSE リクエストを認証する

Cloud Storage FUSE を使用して Cloud Storage バケットをマウントする  |  Google Cloud に書かれている通り、

$ gcloud auth application-default login
$ gcloud auth login

でok

5. Macのシステム機能拡張を有効にする

ここがかなり面倒です。

この状態で 次の6.のステップでマウントしようとすると

となり、機能拡張を有効にする必要があることがわかります。

システム設定 > プライバシーとセキュリティ

から システム機能拡張を有効にする… をクリックします

すると、

となり、起動セキュリティユーティリティを起動することになります。

起動セキュリティユーティリティの起動

メッセージの通り、システム終了させて電源ボタン押したままで起動させます。

手順はオフィシャルのページに書かれています

Appleシリコンを搭載したMacの起動ディスクのセキュリティ設定を変更する - Apple サポート (日本)

「起動オプションを読み込み中..」と表示されるまで電源ボタンを押し続けます。表示されたら電源ボタンは離してokです

  1. 「オプション」をクリック
  2. 「続ける」をクリック
  3. パスワードが分かっているユーザーを選択
  4. 選択して、「次へ」をクリック
  5. 上部メニューの 「ユーティリティ」から 「起動セキュリティユーティリティを起動」 をクリック
  6. セキュリティポリシーの設定に使用したいシステムを選択してください」と出るので ディスクを選択して 「ロック解除」をクリック
  7. セキュリティポリシー で 「低セキュリティ」を選択し、「確認済みの開発元から提供されたカーネル機能拡張のユーザ管理を強化」 をチェック
  8. OKをクリック
  9. 起動ディスクのメニューから「システム終了」をクリック

再起動後、

再び、システム設定 > プライバシーとセキュリティ を開き、

App Storeと確認済みの開発元からのアプリケーションを許可」を選び、「開発元”Benjamin Fleischer”のシステムソフトウェアの読み込みがブロックされました」 を 「許可」します

新しいシステム機能拡張を使用するには再起動が必要です となるので 再度、Mac再起動させます。

6. バケットのマウント

お疲れさまでした。ここまでできたらあとはバケットをマウントするだけです

# マウント
$ gcsfuse バケット名 マウント先ディレクトリ

# アンマウント
$ umount マウント先ディレクトリ

参考記事

論文紹介: Neural Fourier Energy Disaggregation

2023年に読んだNILM(Non-Intrusive Load Monitoring)論文の1つ、Neural Fourier Energy Disaggregation の簡単な紹介をします。

法名は NFED (Neural Fourier Energy Disaggregation) と命名されています。

www.mdpi.com

2行で説明

簡単に言えば、

  • 電力分離(NILM、Energy Disaggregation)の分野で FNet を使ったよ
  • エッジデバイスでも使えそうな計算量、メモリ量になり性能も良かったよ

という論文です。

FNet

コアとなるのがFNetです。 Google Researchの研究者によって提案されたモデルとなります。

arxiv.org

ポイントは

  • トークン混合の手段としてAttention層の代わりにFFTを使った。学習パラメータなしで高速かつ学習も安定しやすい
  • BERTにやや劣るがそれに迫る精度を達成

アーキテクチャは以下のようになっています。

AttentionレイヤーがFourierレイヤーに置き換えられているだけです。

FFTしたあとにその実部だけを使うのが最も性能が出たとされていて、オフィシャルのコードでもそうなっています。

Ablation studyもされており、

トークン混合手段として

  • 通常self-attention
  • 線形モデル
  • FFT
  • ランダム行列
  • トークン混合なし

を比較することによってトークン混合が大事であることを示しています。

この結果は トークン混合手段は何でもよい という[2111.11418] MetaFormer Is Actually What You Need for Vision にも合致しており、納得のいく結果です。

NFEDモデルアーキテクチャ

基本的にFNetと同じです。 ただ、FNetとの違いとしてNFEDでは FFT結果のRealとImagを結合しています。(コードだと51行目)

https://github.com/ChristoferNal/Neural-Fourier-Energy-Disaggregation/blob/main/nfed.py#L51

ここの意図は論文中に特に記載されておらず、気になるところではあります。

性能評価

評価データセット

UK-DALE と REFIT、REDD が使われています。 基本的には UK-DALEでの評価で 異なるデータセットをテストデータとしたときにREFITとREDDが使われています。

Category1 Category2 Category3 Category4
Train UK-DALE 1家庭
UK-DALE 1家庭
UK-DALE 2~3家庭 UK-DALE 2~3家庭
Test UK-DALE 1家庭(trainと同じ) UK-DALE 1家庭(trainと別) UK-DALE 1家庭(trainと別) REFIT or REDDの1家庭

Category3, 4が最もハードな条件、ただ現実世界に近い条件になっています。

リファレンスモデル(ベースラインモデル)

  • S2P (Sequence-to-Point)
  • WGRU (Window GRU)
  • SAED (Self-attentive energy disaggregator)

の3つがリファレンスモデルとして使われています。

SAEDは同じ著者による提案手法ですが S2P、WGRUは他のNILM論文でもベースラインとしてよく登場する馴染みの手法です。

それぞれのアーキテクチャは次の通り。

S2P

WGRU

SAED

結果

今回はモデルの軽量化というのが狙いでもあり、F値やMAEと言った精度評価以外に メモリ容量、推論速度も評価対象に含まれています。

以下、5家電の結果です。

食洗機

洗濯機

冷蔵庫

電子レンジ

ケトル

提案手法であるNFED(青線)が4カテゴリにおける精度面でもシステム面(メモリ、処理速度)でもtopレベルであり良いという主張でした。

ただ、個人的にはオレンジ線のSAEDのほうが良さそうに見えてしまいます。。

所感

どんなに精度が高いモデルであってもシステム要求が厳しいのでは現実世界で使うことが難しいので実用性に目を向けた検討は(特にNILMの世界では)非常に良い方向性だと思いました。

性能比較結果からはリファレンス手法の1つであるSAEDのほうがどうしても良さそうに見えてしまうので、モヤモヤは残ります。

うがった見方をすれば、SAEDも同じ著者の提案手法なので引き立て役だったりするのかもしれませんw

論文の引用数もあまり多くないですし(本日時点で17件。ベースラインモデルのS2Pは505件、WGRUは147件)、今後、他の著者論文でも本論文が引用されるか注目していきたい所です。

Google Home Mini と LINE の連携

想定シナリオ(やりたいこと)

以下の状況で

  • 子どもはスマホをもっていない
  • 学校から帰宅した時、家に両親が不在で子ども1人になる

子どもが帰宅して、スマートスピーカーGoogle Home Mini)に呼びかけると両親のLINEグループに メッセージが送信される

これがやりたいことになります。

参考になった記事

この2つの記事がとても参考になりました。

ただ、2017年という古い記事だったせいか画面の表示内容が違っていたり、記事通りではうまくいかない箇所もありました。

うまく動作させるのに多少試行錯誤が必要だったのでその情報を書いてみます。

同じことをしたい人にとって少しでも参考になればと思います。

大事なポイント

参考記事の中では

  1. スマートスピーカーとIFTTTを連携させる
  2. その後にIFTTTのアプレットを作成

という順序でしたが 先にIFTTTアプレットを作る必要があります。これがハマりどころでした。

なので、(今時点での)正しい順番は

  1. IFTTTアプレットを作成する
  2. Google Home Mini と IFTTTを連携させる

です。

これについては以下のフォーラムの投稿が解決に役立ちました。

Answered: Can't link IFTTT to Google home - Google Nest Community

Dhomasさんの 1 RECOMMENDED ANSWER

Instead, I created the applet first in IFTTT, THEN I linked Google Assistant to IFTTT. It then found "devices" to attach to my Assistant.

がそれです。

IFTTTアプレットの作成

IFTTTで Google Assistant(Google Home Mini)が特定のメッセージを受けたらLINE にメッセージを送るというアプレットを作成します。

IFTTTのアカウント作成をしてダッシュボードに入ったら、My Applets から Create をクリック

If This の Add をクリック、Choose a service で Google Assistant を選びます

続いて、トリガーを作成します

参考記事の中ではトリガーが何種類かあるようでしたが、"Activate scene" の1個しか選択肢はありませんでした

Scene name を入力します。

OK Google, アクティベート {入力したシーン名}」でトリガーが発動されるようになります

続いて、Then Thatのパート。Add をクリックし、

LINE を選択します

選択できるのは Send message だけです。これを選びます

LINEアカウントとの連携後、宛先(Recipient)を選びます。 プルダウンを開くとLINEグループのリストが表示されるので該当するグループ(今回のシナリオでは両親のグループ)を選択します

Continueをクリックし、

レビューをしたらFinishを押して完了となります

Google Home Mini と IFTTTの連携

まず、Google Homeのアプリをスマートホンにインストールしておきます。

アプリを開き、画面右下の設定ボタンをタップ

サービスのセクションの「Googleと連携させる」 をタップ

虫眼鏡の検索ボタンからIFTTTを選択し、

次へをタップ

IFTTTにログインしてAuthorizeをタップしたら

リンク中のメッセージが出て、その後設定完了となります

大事なポイントで書いてますが、最初にGoogle Homeの設定を進めてしまうと、ここで以下のエラーメッセージが出てリンク失敗となります

IFTTT no devices were found in your ifttt account you may need to setup these devices ifttt first. if you already set up devices, they may not be available due to temproary error. please wait a few minutes and try again

成功すると以下のようにスマートスピーカーへの呼びかけに従ってLINEグループにメッセージが飛んでくるようになります

Make(旧Integromat)でWebサービスにログインした後の遷移先ページを取得する方法

前回の記事の中で Makeを使って、Webサービス(サークルスクエア)からイベントリストを抜き出して、Googleカレンダーに登録するということをやりました。

Webサービスにログインしてログイン後に遷移するページのHTMLを取得することはいちおう可能だったのですが その後のイベントリスト取得を Text parser のみで処理するのは気が遠くなるのでMakeのみでWebサービスからのスクレイピングをすることを断念しました。

ただ、ログイン後の遷移先ページのHTML取得のやり方は苦労したので今回紹介します。

【つぶやき】Makeはやりたいことに対しての詳しいドキュメントが見つからず、思ったよりつまずきが多かったです。

他のサイトで全く同じようにいくかはわかりませんが少しでも参考になればと思います

やりたいこと

Webサービスのログイン画面

ログイン画面

アカウントとパスワードを入力するとホームに飛びます。

このホームのHTMLを取得することが目標になります。

流れとしては以下になります。

  1. ログインページをGETメソッドで取得
  2. アカウントとパスワードをPOSTで送信
  3. 認証成功したらhomeへ自動遷移する
  4. homeのHTMLを取得する

シナリオ全体像

シナリオは以下のようなモジュールで構成されます。

Makeのみでスクレイピングを完結しようとすればこの4つのモジュールのあとに Text parser が鬼のように続くことになると思います

TL;DR

先に大事なポイントをまとめます

  • 前段後段の2つのHTTPモジュールで共にShare cookies with other HTTP modules を Yes にする
  • 前段のGETの応答の中のCookie headers の値を後段のPOSTするときに再利用する
  • POSTする後段のリクエストで Follow redirectを Yes、Follow all redirect も Yes にする

あとは、前段のGETの応答のbodyからCSRFトークンを抽出し、後段のPOSTするときにアカウント、パスワードとともにCSRFトークンをパラメータとしてセットすればokです

各モジュールの説明

HTTP: Make a request (#1)

ログインページを取得します。

ログインページ取得後、やることは2つになります。

  1. CSRFトークンを抽出する(Text parserでパターンマッチして抽出する)
  2. 応答のCookieヘッダからセッション情報の値を抽出する

1つ目は次のText parserのモジュールで対応します。

2つ目は以下の赤枠で囲った部分になりますが、後続のモジュールから直接参照できます。ただ、なぜか circlesquare_session のほうは参照できなかったので一工夫必要になります

Text parser:Match pattern (#1)

正規表現にてCSRFトークンを抽出します

Text parser:Replace (#2)

1番目のHTTPリクエストの応答で含まれているCookieヘッダ(XSRF_TOKENとcirclesquare_session)のうち、circlesquare_sessionが後段のHTTPモジュールからなぜか参照できないので、値をコピーします

HTTP: Make a request (#2)

ここでやっていること

  • セッション情報の値をCookieヘッダとしてセット
  • CSRFトークンをPOSTパラメータに追加

気をつけることは 2つのHTTPモジュールで共にShare cookies with other HTTP modules を Yes にすることです。

これをしてないと、419 エラーになります。

419 はこれまで出会ったことなかったですが 以下の定義により Laravel固有のステータスコードCSRF検証が失敗したときに出るみたいです。

HTTP response status code 419 Page Expired is an unofficial client error that is Laravel-specific and returned by the server to indicate that the Cross-Site Request Forgery (CSRF) validation has failed.

また、 Follow all redirect を No にしていると 以下のようなHTMLとともに 302 が返ってくるので Follow all redirect を Yes にします。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url='https://www.c-sqr.net/home'" />

        <title>Redirecting to https://www.c-sqr.net/home</title>
    </head>
    <body>
        Redirecting to <a href="https://www.c-sqr.net/home">https://www.c-sqr.net/home</a>.
    </body>
</html>

Follow all redirect を Yes にしていると、200のレスポンスコードが返ってきて遷移後のページのHTMLが応答として得られます。

以上で無事にログイン後の遷移先ページのHTMLを取得できました。

ただ、ここからText Parserを何個も用いてイベント情報のリストを抽出するのは大変そうだったので結局は自前のWebサービスを実装して情報抽出しています。