Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - 4.Power Automate編 -

# 1.やったこと
iPhoneのアクティビティアプリのスクショを画像認識して、筋トレ結果を抽出、データを格納してダッシュボードで表示する…までを、Power Platformの各種サービスを駆使してノンコーディングでやってみたことのうち、**Power Automate**でやったことのメモです。

1. [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - AI Builder編 -](https://qiita.com/miokawa/items/17d84d8811fe38ff4704)
2. [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power Apps編 -] (https://qiita.com/miokawa/items/0f3dc6ac6a1be01984d6)
3. [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Common Data Service編 -](https://qiita.com/miokawa/items/da330e778afabf46579d)
4. [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power Automate編 -](https://qiita.com/miokawa/items/2ca2c75fdb52fcc90e78)←コレ
5. [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power BI編 -](https://qiita.com/miokawa/items/c7afe408e076cb9f7578)

人恋しさと運動不足解消のため、定期的にオンラインフィットネス（Teams繋ぎながらyoutubeのトレーニング動画を流してみんなでやる）を会社の人とやり始めたことがきっかけで作りました。

最終的な成果物はこんな感じ（細かいデザイン方法については触れません）。
<img width="250" alt="サンプルスクショ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/5369c570-2e83-4f8e-c113-e0be8f557090.jpeg"> <img width="250" alt="サンプルスクショ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/badb9fb8-1fea-ea0e-387b-f1a46ac248b9.jpeg"> <img width="250" alt="サンプルスクショ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/ed233619-7794-1379-2ef0-c5e85ac2b356.jpeg">

※試行錯誤した結果、こうしたらできた！って感じなので、これが一番スマートなのかどうかは不明ですのでご注意ください。

# 2.本アプリでのPower Platformの各サービスの役割
- **Power Apps**：iPhoneのアクティビティアプリのスクショをアップロードする。Power BIで筋トレ記録見られる。
- **AI Builder**：アクティビティアプリのスクショに含まれる筋トレ時間、消費カロリー、日付などを画像認識する
- **Power Automate**：Power Appsのアップロードボタンをトリガーに、アップロードされたスクショをAI Builderに投げ、結果のデータをCommon Data Serviceに格納する
- **Common Data Service**：ひたすら筋トレ結果を格納する
- **Power BI**：Common Data Serviceに格納された筋トレ成果たちをそれっぽく表示する

図にすると以下のような感じです。
気づいたら割といろいろ使ってた。わお。

![筋トレアプリ図解.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/17447ad0-bd5a-0f5f-e48a-20bddeeb914e.png)

# 3.開発環境
今回はこちらの無料ライセンスを使いました。
[Power Apps Community Plan](https://powerapps.microsoft.com/ja-jp/communityplan/)


# 4.実現したいこと
[Power Apps編](https://qiita.com/miokawa/items/0f3dc6ac6a1be01984d6)で作成したPower Appsのアプリをトリガーに、[AI Builder編](https://qiita.com/miokawa/items/17d84d8811fe38ff4704)で作成したAIモデルを実行し、スクショから抽出した各種トレーニングデータを加工し、以下の値を[Common Data Service編](https://qiita.com/miokawa/items/da330e778afabf46579d)で作成したCommon Data Serviceのテーブルへ格納するPower Automateのフローを作成します。

- Date（日付のみ）
- Training Category（テキスト）
- Active Kilocalories（整数）
- Avg. Heart Rate（整数）
- Total Training Minutes（整数）


# 5.作成過程
## 5.1 フローへアクセス
[Power Apps](https://make.powerapps.com/)にログインし、**フロー**から[Power Apps編](https://qiita.com/miokawa/items/0f3dc6ac6a1be01984d6)で作成したフローを開きます。
以下のような状態になっているかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/81eb8ae5-03d9-dae2-d282-8a4bed7ab5ed.png)

これから、Common Data Serviceにデータを格納するために、AI Builderが抽出したデータを加工していきます。
基本的には、**新しいステップ**から**変数**、**変数を初期化する**というアクションを追加して、加工していきます。

## 5.2 Date
AIモデルから抽出されるのは、曜日、日、月の情報ですが、曜日のデータはいらないし、年のデータがほしいところです。
年のデータはスクショから取得できないので、アップロードされた時点の年のデータを使うことにします。
**名前**に変数名**Year**、**種類**に**文字列**を選択し、**値**は動的なコンテンツから**式**のタブを選択して以下を入力して**更新**をクリックします。
やっていることは、[utcNow関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#utcnow)でまずUTC時間を取得しつつ、日本時間に変換した上で、yyyy/MM/ddの形にして、[substring関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#substring)で頭の0文字から4文字目まで（年の部分のみ）を抽出しています。

```Yearデータの設定
substring(convertFromUtc(utcNow(),'Tokyo Standard Time','yyyy/MM/dd'),0,4)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/b25a1b49-5fb0-53af-3ba3-d14e170145e3.png)

次に、AIモデルから抽出される月、日のデータと年のデータを連結し、Date変数を作ってみたいと思います。
同じく変数を初期化するアクションを追加し、動的なコンテンツから`月 value`、`日 value`、`Year`を追加し、`日 value`、と`Year`の間に「,」を入れて、MM dd,yyyyの形にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/33893258-b348-b21d-d30a-d57163ce134d.png)

## 5.3 Active Kilocalories
こちらは単純で、AIモデルから抽出されるデータには、「116KCAL」という形で単位がついてしまっているので、そのまま保存してしまうと数値として計算したりできないため、「KCAL」を除外するようにします。
変数名を付け、種類を**文字列**に設定したら、**値**の部分で動的なコンテンツから**式**を選択し、[replace関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#replace)を検索、選択したあと、括弧の中に**動的なコンテンツ**から`アクティブキロカロリー value`を選択します。
勝手に、`outputs('フォームの情報を処理して保存する')?['body/responsev2/predictionOutput/labels/_xxxxxxxxxx/value']`等に変換されますが、大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/08fd0101-501d-7351-49f4-aa1b6742960b.png)

そして二つ目の引数に、除外したい`KCAL`を入力し、代わりに`''(何もなし)`を入れるように三つ目の引数に入力します。

さらに、Common Data Service側では、この項目は整数型として用意しているので、[int関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#int)で文字列を整数に変換しておきます。
最終的に入力する式は以下の通りです。

```
int(replace(outputs('フォームの情報を処理して保存する')?['body/responsev2/predictionOutput/labels/_xxxxxxxxxx/value'],'KCAL',''))
```

## 5.4 Avg. Heart Rate
Active Kilocaloriesと同じく、「130BPM」という形になってしまうので、「BPM」を除外します。
方法は全く同じなので割愛します。

## 5.5 Total Training Minutes
AIモデルから抽出された状態だと、「0:39:23」という形式になっています。このままだとトレーニング時間の計算ができないので、一旦分単位にしたい（秒は切り捨て）と思います。
（私はこの形式のままPower BIでうまく計算する方法が見つけられませんでした。もしあればそちらの方法で…）

だいぶ回りくどいやり方になってしまって、他にもっといい方法があるかもしれませんが、一応メモとして記載します。

**変数を初期化する**アクションを追加し、名前を付けたら、種類は**アレイ**にします。
そして、**動的なコンテンツ**の**式**から[split関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#split)を検索し、一つ目の引数に`合計時間 value`を、二つ目の引数に`:`を入れます。これにより、「0:39:23」の文字列が、「0」と「39」と「23」に分割され、配列に格納されます。
入力する式は以下の通りとなります。

```
split(outputs('フォームの情報を処理して保存する')?split(outputs('フォームの情報を処理して保存する')?['body/responsev2/predictionOutput/labels/_xxxxxxxxxx/value'],':')
```

続いての手順は、今後の式を見やすくするために、分割した配列の0番目の数字（時間）と1番目の数字（分）の変数を整数型で定義しておきます。
**変数を初期化する**アクションで、変数に名前を付けたら、種類は**整数**にします。
そして**動的なコンテンツ**の**式**から[int関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#int)を検索し、引数として、**動的なコンテンツ**から、ひとつ前の手順で作成した配列を選択、配列の番号を`[0]`や`[1]`の形で追加します。
以下は[0]のパターン、つまり時間数を格納した配列の場合を示しています。同様に分の部分も**変数を初期化する**アクションを追加します。

```
int(variables('Time Array')[0])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/c7653965-7e40-d4d5-fd6c-c361e74581c1.png)

ここまできたら、あとは単純に**時間数×60+分数=全体のトレーニング時間（分）**を格納する**変数を初期化する**アクションを追加していきます。
変数に名前を付けたら、種類は**整数**にして、[add関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#add)と[mul関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#mul)を使って、掛け算と足し算をします。

```
add(mul(variables('Hour'),60),variables('Minute'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/e55fa613-0f70-18ce-26c0-04d59d6114e1.png)

## 5.6 Common Data Serviceへのレコードの追加
いよいよCommon Data Serviceのレコードを追加します。

**Common Data Service**の**新しいレコードの作成**アクションを選択します。
エンティティ名で[Common Data Service編](https://qiita.com/miokawa/items/da330e778afabf46579d)で作成したテーブルを選択すると、そこで追加した列名が含まれたボックスが出てきますので、それぞれ必要なデータを設定していきます。

**Trainin Data**が必須になっていますが、こちらは[Common Data Service編](https://qiita.com/miokawa/items/da330e778afabf46579d)でテーブルを作成した際の**プライマリ名の列**に該当します。
[公式サイト](https://docs.microsoft.com/ja-jp/powerapps/maker/common-data-service/data-platform-create-entity)の説明によると、「他のテーブルとの関係を確立する際の列の検索処理に使用されます。 通常プライマリ列には、そのテーブルに格納されているデータの名称または主な説明が格納されています。 」とのことなのですが、現状使う予定がないので、ひとまず以下の通り、`Training Data - レコード作成日時（以下の式）`をいれておきました。

```
convertFromUtc(utcNow(),'Tokyo Standard Time')
```

**Active Kilocalories**、**Avg. Heart Rate**、**Date**、**Total Training Minutes**に関しては、いままで設定した変数を**動的なコンテンツ**から選択すればOKです。
**Training Category**はAIモデルから抽出されたものをそのまま選択します。

<img width="500" alt="サンプルスクショ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/06cb8d6b-83ae-008c-15cf-b0fb6951b53b.png">



他、たくさん空白がありますが、特に問題ありません。

## 5.7 テスト
それでは、テストしてみたいと思います。
[Power Apps編](https://qiita.com/miokawa/items/0f3dc6ac6a1be01984d6)で作成したアプリをプレビューで起動し、スクショをアップロードしてみます。
左上の←ボタンから、Power Automateのフローの概要画面に移動し、実行履歴を確認します。
フローがエラーにならずに実行され、**新しいレコードの追加**アクションの詳細を展開し、正しくデータが格納されたことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/24601b92-2c5b-5186-2fe6-079bb946fbef.png)

ちなみに、Common Data Serviceの**ビュー**タブから適当なビューを選び、列を追加すると、データの中身が見られるので、きちんと格納されていることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/bf7b990d-6d78-b8d8-97b2-ad5c4de92fa9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596292/bef00db1-b66f-c375-98bf-5d596eedc58b.png)

# 6.次のステップ
いくつかサンプルでスクショをアップロードし、Common Data Serviceのデータを増やしておきましょう。
そのあと、[Power BI編](https://qiita.com/miokawa/items/c7afe408e076cb9f7578)でダッシュボードを作っていきます。