1.やったこと
iPhoneのアクティビティアプリのスクショを画像認識して、筋トレ結果を抽出、データを格納してダッシュボードで表示する…までを、Power Platformの各種サービスを駆使してノンコーディングでやってみたことのうち、Power Automateでやったことのメモです。
- Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - AI Builder編 -
- [Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power Apps編 -] (https://qiita.com/miokawa/items/0f3dc6ac6a1be01984d6)
- Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Common Data Service編 -
- Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power Automate編 -←コレ
- Power Platformでノンコーディングで筋トレ成果を記録するアプリを作ってみた - Power BI編 -
人恋しさと運動不足解消のため、定期的にオンラインフィットネス(Teams繋ぎながらyoutubeのトレーニング動画を流してみんなでやる)を会社の人とやり始めたことがきっかけで作りました。
最終的な成果物はこんな感じ(細かいデザイン方法については触れません)。
※試行錯誤した結果、こうしたらできた!って感じなので、これが一番スマートなのかどうかは不明ですのでご注意ください。
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に格納された筋トレ成果たちをそれっぽく表示する
図にすると以下のような感じです。
気づいたら割といろいろ使ってた。わお。
3.開発環境
今回はこちらの無料ライセンスを使いました。
Power Apps Community Plan
4.実現したいこと
Power Apps編で作成したPower Appsのアプリをトリガーに、AI Builder編で作成したAIモデルを実行し、スクショから抽出した各種トレーニングデータを加工し、以下の値をCommon Data Service編で作成したCommon Data Serviceのテーブルへ格納するPower Automateのフローを作成します。
- Date(日付のみ)
- Training Category(テキスト)
- Active Kilocalories(整数)
- Avg. Heart Rate(整数)
- Total Training Minutes(整数)
5.作成過程
5.1 フローへアクセス
Power Appsにログインし、フローからPower Apps編で作成したフローを開きます。
以下のような状態になっているかと思います。
これから、Common Data Serviceにデータを格納するために、AI Builderが抽出したデータを加工していきます。
基本的には、新しいステップから変数、変数を初期化するというアクションを追加して、加工していきます。
5.2 Date
AIモデルから抽出されるのは、曜日、日、月の情報ですが、曜日のデータはいらないし、年のデータがほしいところです。
年のデータはスクショから取得できないので、アップロードされた時点の年のデータを使うことにします。
名前に変数名Year、種類に文字列を選択し、値は動的なコンテンツから式のタブを選択して以下を入力して更新をクリックします。
やっていることは、utcNow関数でまずUTC時間を取得しつつ、日本時間に変換した上で、yyyy/MM/ddの形にして、substring関数で頭の0文字から4文字目まで(年の部分のみ)を抽出しています。
substring(convertFromUtc(utcNow(),'Tokyo Standard Time','yyyy/MM/dd'),0,4)
次に、AIモデルから抽出される月、日のデータと年のデータを連結し、Date変数を作ってみたいと思います。
同じく変数を初期化するアクションを追加し、動的なコンテンツから月 value
、日 value
、Year
を追加し、日 value
、とYear
の間に「,」を入れて、MM dd,yyyyの形にします。
5.3 Active Kilocalories
こちらは単純で、AIモデルから抽出されるデータには、「116KCAL」という形で単位がついてしまっているので、そのまま保存してしまうと数値として計算したりできないため、「KCAL」を除外するようにします。
変数名を付け、種類を文字列に設定したら、値の部分で動的なコンテンツから式を選択し、replace関数を検索、選択したあと、括弧の中に動的なコンテンツからアクティブキロカロリー value
を選択します。
勝手に、outputs('フォームの情報を処理して保存する')?['body/responsev2/predictionOutput/labels/_xxxxxxxxxx/value']
等に変換されますが、大丈夫です。
そして二つ目の引数に、除外したいKCAL
を入力し、代わりに''(何もなし)
を入れるように三つ目の引数に入力します。
さらに、Common Data Service側では、この項目は整数型として用意しているので、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関数を検索し、一つ目の引数に合計時間 value
を、二つ目の引数に:
を入れます。これにより、「0:39:23」の文字列が、「0」と「39」と「23」に分割され、配列に格納されます。
入力する式は以下の通りとなります。
split(outputs('フォームの情報を処理して保存する')?split(outputs('フォームの情報を処理して保存する')?['body/responsev2/predictionOutput/labels/_xxxxxxxxxx/value'],':')
続いての手順は、今後の式を見やすくするために、分割した配列の0番目の数字(時間)と1番目の数字(分)の変数を整数型で定義しておきます。
変数を初期化するアクションで、変数に名前を付けたら、種類は整数にします。
そして動的なコンテンツの式からint関数を検索し、引数として、動的なコンテンツから、ひとつ前の手順で作成した配列を選択、配列の番号を[0]
や[1]
の形で追加します。
以下は[0]のパターン、つまり時間数を格納した配列の場合を示しています。同様に分の部分も変数を初期化するアクションを追加します。
int(variables('Time Array')[0])
ここまできたら、あとは単純に時間数×60+分数=全体のトレーニング時間(分)を格納する変数を初期化するアクションを追加していきます。
変数に名前を付けたら、種類は整数にして、add関数とmul関数を使って、掛け算と足し算をします。
add(mul(variables('Hour'),60),variables('Minute'))
5.6 Common Data Serviceへのレコードの追加
いよいよCommon Data Serviceのレコードを追加します。
Common Data Serviceの新しいレコードの作成アクションを選択します。
エンティティ名でCommon Data Service編で作成したテーブルを選択すると、そこで追加した列名が含まれたボックスが出てきますので、それぞれ必要なデータを設定していきます。
Trainin Dataが必須になっていますが、こちらはCommon Data Service編でテーブルを作成した際のプライマリ名の列に該当します。
公式サイトの説明によると、「他のテーブルとの関係を確立する際の列の検索処理に使用されます。 通常プライマリ列には、そのテーブルに格納されているデータの名称または主な説明が格納されています。 」とのことなのですが、現状使う予定がないので、ひとまず以下の通り、Training Data - レコード作成日時(以下の式)
をいれておきました。
convertFromUtc(utcNow(),'Tokyo Standard Time')
Active Kilocalories、Avg. Heart Rate、Date、Total Training Minutesに関しては、いままで設定した変数を動的なコンテンツから選択すればOKです。
Training CategoryはAIモデルから抽出されたものをそのまま選択します。

他、たくさん空白がありますが、特に問題ありません。
5.7 テスト
それでは、テストしてみたいと思います。
Power Apps編で作成したアプリをプレビューで起動し、スクショをアップロードしてみます。
左上の←ボタンから、Power Automateのフローの概要画面に移動し、実行履歴を確認します。
フローがエラーにならずに実行され、新しいレコードの追加アクションの詳細を展開し、正しくデータが格納されたことを確認します。
ちなみに、Common Data Serviceのビュータブから適当なビューを選び、列を追加すると、データの中身が見られるので、きちんと格納されていることを確認できます。
6.次のステップ
いくつかサンプルでスクショをアップロードし、Common Data Serviceのデータを増やしておきましょう。
そのあと、Power BI編でダッシュボードを作っていきます。