Power Automate Desktop「簡易　見守りカメラをつくってみた」

### 概要

Power AutomateとPower Automate Desktopを連携させ、モバイル端末からローカルPCのWEBカメラで撮影、Teamsに投稿します。
![ipc2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/7764bf5b-2d77-f198-69b9-ac961ca6432c.gif)


## 注意事項

* Pythonを使います。
* アテンド型RPAのユーザーごとのライセンス（試用可）が必要になります。
* PA、PAD連携にはWindows 10 pro必須です。
* 自己責任でお願いいたします。

## 環境等

* Windows 10 pro 20H2
* モバイル版Power AutomateおよびTeams
* 2021年5月時点での最新版PADおよびオンプレミスデータゲートウェイを使用しています。
* Python3.8.10
* https://www.python.org/ のインストーラーを使用しています。
* グローバル環境に以下のライブラリを個別にインストールしてあります。
  - OpenCV 4.4.0.46
  - pyperclip 1.8.1
  - numpy 1.18.5

Pythonについてはhttps://www.python.jp/index.html さまの環境構築ガイドを参考にしていただければと思います。

# やること

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/2411b89a-2d38-0e98-4228-dc9e5b0c3ed6.png)


1. Power AutomateのモバイルアプリからPower Automate Desktopに起動指示
2. PCのPython環境でpyファイルを実行
3. Webカメラで撮影
4. 画像を圧縮処理、Base64変換をおこないPower Automate Desktopに返却
5. Incoming Web hookを利用してTeamsにPOST

1の部分は最後に作ります。

## Power Automate Desktopフロー

PADのコード内にpythonスクリプトを埋め込んで生成するようになっています。今回のフローではPythonスクリプトにPAD側から変数を渡していないので、pyファイルを作成し任意の場所に置く場合は4、5、6のアクションのみで済みます。
![232532.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/3a2c9f94-e0f4-e519-8f8e-3c9f42d7552a.jpeg)


####1. 現在の日時を取得します。

Teamsのメッセージに入れたかったので使用しました。

####2. Windows環境変数を取得

   TEMPフォルダーへのパスを取得しています。
      ![](2021-05-06-21-10-07.png)
####3. テキストをファイルに書き込みます

   PythonスクリプトをTEMPフォルダーに作成します。
   複数行テキストは標準機能で今のところ使えませんので方法は[過去記事](https://qiita.com/sys_zero/items/0f40820e59d37561e353#python%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B)を参照ください。

 ```python:Python
import cv2
import binascii
import pyperclip

# Webカメラから入力
cap = cv2.VideoCapture(1)
# 画像を取得
ret, img = cap.read()
# カメラ解放
cap.release()
# リサイズ
img2 = cv2.resize(img , (320,240))
# 画像を圧縮
ret, data = cv2.imencode(".jpg", img2,[cv2.IMWRITE_JPEG_QUALITY, 40])
# Base64に変換
base64string = binascii.b2a_base64(data).decode("ascii").strip()
# クリップボードに出力
pyperclip.copy(base64string)

 ```
* OpenCVおよびpyperclipはグローバル環境にpipしてあります。
* ```cap = cv2.VideoCapture(1)```の1の部分がWebカメラのデバイス番号になるので環境に合わせて書き換えてください。
* 私のWebカメラのキャプチャ元画像は640X480でした。Teamsにbase64でPostするとき、データが15kbyteを超えたあたりでエラーになるため、320X240にリサイズ後cv2.IMWRITE_JPEG_QUALITYを40にして調整しています。
* Base64に変換後余分な空白や改行を削除、Pyperclipを使ってWindows側のクリップボードに保存しています。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/810ea07c-b7c8-c234-d3fa-e50bac461a8a.png)

####4.DOSコマンドの実行

   変数は生成していません。TEMPフォルダーに保存したcapture.pyを実行します。
   ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/99234fb6-d0b4-c9ad-47fb-1f7cc9c36944.png)

####5.クリップボードテキストを取得

   クリップボードに格納されているBase64データを%ClipboardText%に代入します。
####6.Webサービスを呼び出します

   このアクションからIncoming Webhook経由でTeamsに画像を投稿します。
##### Teamasの設定

   - 投稿用のプライベートチームを作成します。メンバー追加は必要ありません。
   ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/24fd189b-ddd4-7f89-3c9f-e759f2c229cd.png)


   - コネクタを追加します。
   ![connect.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/4f723235-9c88-b453-1909-8acffe440be3.jpeg)


   - incoming webhookを検索して追加します。
   ![income.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/752c7a60-3863-c918-d41f-60ffe26ac81b.jpeg)


   - 再度コネクタを開いてIncoming webhookを構成します。
   ![kousei.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/09b3c25e-05fd-60af-bdd7-ba4557e1d53b.jpeg)


   - 名前とアイコンを適宜設定して作成します。

   ![name.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/2395871f-ab52-20a4-8aaa-711e0e2ea153.jpeg)


   - 作成されるとURLが生成されるのでコピーしておきます。後からでも構成済みから選択すると再コピー可能です。

   ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/905d6d1f-1625-e8c2-f8f8-98e2a3755b1a.png)

##### 「Webサービスを呼び出します」アクションの設定

   ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/6dbbf970-e236-015b-8848-21304642a5ea.png)

   - URL部分にTeamsからコピーしたURLを貼り付けます。
   - メソッド　POST
   - コンテンツタイプ　application/json
   - 要求本文　カードをJSON形式で投稿しています。imageプロパティにdata URIを使って画像を投稿します。クリップボードから取得したBase64データを挿入しています。

  ```JSON:JSON
 {
    "@type": "MessageCard",
    "title": "Image POST %CurrentDateTime%",
    "text": "キャプチャしました！",
    "sections": [
        {
            "images": [
                {
                    "image": "data:image/jpeg;base64,%ClipboardText%"
                }
            ]
        }
    ]
}
```
　
　

####7.ファイルの削除

   TEMPフォルダーに作ったpythonスクリプトを削除しています。

### 確認

テストしてみます。

![2021-05-08-02-12-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/ef1ae667-8db5-9589-d41e-2f924480958f.png)


## コード

```r
DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
System.GetEnvironmentVariable Name: $'''TEMP''' Value=> EnvironmentVariableValue
File.WriteText File: $'''%EnvironmentVariableValue%\\capture.py''' TextToWrite: $'''import cv2
import binascii
import pyperclip

# Webカメラから入力
cap = cv2.VideoCapture(1)
# 画像を取得
ret, img = cap.read()
# カメラ解放
cap.release()
# リサイズ
img2 = cv2.resize(img , (320,240))
# 画像を圧縮
ret, data = cv2.imencode(\".jpg\", img2,[cv2.IMWRITE_JPEG_QUALITY, 40])
# Base64に変換
base64string = binascii.b2a_base64(data).decode(\"ascii\").strip()
# クリップボードに出力
pyperclip.copy(base64string)''' AppendNewLine: False IfFileExists: File.IfFileExists.Overwrite Encoding: File.FileEncoding.UTF8NoBOM
System.RunDOSCommand DOSCommandOrApplication: $'''%EnvironmentVariableValue%\\capture.py'''
Clipboard.GetText Text=> ClipboardText
Web.InvokeWebService Url: $'''Your URL''' Method: Web.Method.Post Accept: $'''application/json''' ContentType: $'''application/json''' RequestBody: $'''{
    \"@type\": \"MessageCard\",
    \"title\": \"Image POST %CurrentDateTime%\",
    \"text\": \"キャプチャしました！\",
    \"sections\": [
        {
            \"images\": [
                {
                    \"image\": \"data:image/jpeg;base64,%ClipboardText%\"
                }
            ]
        }
    ]
}''' ConnectionTimeout: 30 FollowRedirection: True ClearCookies: False FailOnErrorStatus: False EncodeRequestBody: False UserAgent: $'''Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6''' Encoding: Web.Encoding.AutoDetect AcceptUntrustedCertificates: False ResponseHeaders=> WebServiceResponseHeaders Response=> WebServiceResponse StatusCode=> StatusCode
File.Delete Files: $'''%EnvironmentVariableValue%\\capture.py'''
```

## Power Automateフローの作成

インスタントクラウドフローを作成します。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/9d2a1f1e-d982-b0b6-5269-a00b6be8c821.png)


「Power Automate Desktopで構築したフローを実行する」で先に作成したPADのフローを選択し、実行モードはライセンスにあわせます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/c820f980-e720-3034-c5f2-0a1b64468327.png)


保存してテストします。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680039/ec045ff8-4e0d-91fc-0784-b0fcc2587c2c.png)

これでPower Automateモバイルアプリから操作可能です。

## まとめ

* モバイル端末からルータ内のPCに難しい設定なくアクセスし画像撮影できました。
* 撮影した画像をIncoming Webhookを使うことでPADから投稿できました。
* クリップボード経由のデータ連携は安定していました。
* プライバシーの問題を気にしないなら3000～5000円で見守りカメラは買えるのでネタのひとつとしてお考えください。
* 「Webサービスを呼び出します」アクションは色々応用できますね！

## 参考

https://docs.microsoft.com/ja-jp/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using
https://teratail.com/questions/288950
https://stackoverflow.com/questions/56853198/teams-invoke-webrequest-sending-base64-string-png-to-teams