Automation Anywhere v11でControl Room API経由でBotを実行する

Automation Anywhere v11.xでは、大きく分けてControl RoomからBotを実行する方法と、Enterprise ClientからBotを実行する方法があります。前者はどちらかというと本来の**サーバー型RPA**での実行形態であり、アクセスしているPC以外でのデバイスの実行も含め、Control Roomが管理しているあらゆるデバイスでの実行が可能です。一方、Enterprise Clientからの実行は、操作をしているPC自体での実行を前提とした**デスクトップ型RPA**的な実行形態であると言えるでしょう。

Control RoomからBotを実行する形態には、Control RoomのUIを使う方法と、APIを使う方法の2種類があります。今回は、APIを使ってBotを実行してみたいと思います。

※ [**A2019の場合はこちらを参照ください。**](https://qiita.com/RPAbot/items/8c313f137ff089a0014d)

# やりたいこと
Bot Creator権限を持っている人であれば自分が開発したBotをそのままクライアントから実行、ということをよくやっているかもしれません。Bot Creatorを持っていなくても、ローカルPCからプログラムを実行することで、Control Room APIを呼び出してBotを実行できるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/1abf0bec-bb5f-091b-3924-dbaa59e11c14.png)

* 実行するBot: "Messagebox.atmx"
* 実行するユーザー: "runuser"


# 実行するための要件
API経由でEnterprise Clientに指令を出すための**Unattended Bot Runner権限のアカウントを作っておきます。**(Bot CreatorやAttended Bot Runnerは不可) このアカウントでローカルのEnterprise Clientにサインインした状態にしておきます。

また、**実行したいBotはクライアントリポジトリからサーバーリポジトリにアップロードしておく**必要があります。(Enterprise Clientの「管理」-「リポジトリ」からアクセス)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/ee16bca1-6c6a-3b1d-65a1-4cbaf36d80bc.png)

サーバーリポジトリにアップすると、Control Roomの「マイBot」からも見えるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/fcf54dc6-66f3-ca83-2c87-44083a6b2d66.png)

APIを呼ぶときに使用するアカウントは、**Control Room経由でBotを実行できる権限を持っている**必要があります。

**curlコマンド**は元々Linuxのコマンドですが、Windows 10でもApril 2018 Updateから標準コマンドとなっており、特に追加インストールなく実行できます。もしこの要件を満たしていないOSでcurlコマンドを使いたい場合は、必要なモジュールをダウンロードしてインストールしてください。

* [Windows 環境における curl コマンド利用のまとめ (平成最終版)](https://qiita.com/yamachan360/items/8c928738289cd518eec8) by @yamachan360 さん

また、curlコマンドで返されるJSONをコマンドラインで加工する**jqコマンド**はWindowsでは標準では実装されていないため、[ここ](https://stedolan.github.io/jq/)からWindows版 (jq-win64)をダウンロードして、パスが通る場所にコピーしておきます。

# Control Room APIをSwagger UIでテストしてみる
`http://(v11ControlRoomURL)/Swagger/`を見てみると、以下の画面が表示され、利用可能なControl Room API一覧を見ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/609e4da2-2859-f06c-2f5f-edb24d3c74a5.png)

この中で、以下の順番にAPIを呼び出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/32a6e1bb-a63e-1328-4244-d90c6e7df5ca.png)
UIの中では①②を使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/37d9d790-a81a-8407-6bfc-c8a2ca03c26a.png)


### Swagger UIによる操作方法

1. まず、Authentication APIのページを開きます。(上記①のリンク)<br/>`http://(v11ControlRoomURL)/swagger/ui/?url=/swagger/api/v1/auth-api-supported.yaml`<br/>
開いた後のページ内でSchemesでHTTP/HTTPSの適切なほうを選択した後、`/authentication` (ユーザーに権限を与える)メソッドのセクションを開いて、「Try it out」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/fe24dba1-da71-de22-a4a0-65bfb65497f4.png)
2. body部分が編集できるようになるので、apiKeyを消して、username、passwordに適切なユーザー名とパスワードを指定して、「Execute」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/2b0af958-5aea-c68a-faf4-a2206588f459.png)
3. 正常に実行されると、Response部分にapiKeyが返ります。下記の図のtokenの内容 "`eyJ...zHg`"の部分です。この部分をくりっぴボードにコピーしておきます。このtoken (apiKey)は同じユーザーでControl Roomにサインインすると期限が切れてしまうので注意してください。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/faec2024-9a16-9e55-918c-34963fe516ee.png)
4. 次に、Automation Management APIのページを開きます。(上記②のリンク)<br/>`http://(v11ControlRoomURL)/swagger/ui/?url=/swagger/api/v1/auth-api-supported.yaml`<br/>開いた後のページ内でSchemesでHTTP/HTTPSの適切なほうを選択した後、「Authorize」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/ff5f9bc9-0873-59d0-ac3f-30db097ce301.png)
5. 開いたダイアログボックスで、先ほどクリップボードにコピーしておいたtoken (apiKey) をValueにペーストして「Authorize」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/2e79b330-dbee-8b0c-6553-549aad39e69f.png)
6. 「Close」ボタンを押してダイアログボックスを終了します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/04792fa7-2a04-8d24-59d6-3b25ad7ea8ea.png)<br/>これにより、「Authorize」ボタンの中の鍵のアイコンが、はずれた状態からかかった状態になります。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/a01d3d13-d3b9-4aff-b411-4073ea814958.png)
7. `/automations/deploy` (オートメーションを作成後、すぐに展開)メソッドのセクションを開いて「Try it out」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/bdd8b254-e7e2-700c-7bcc-1b35ce77fb4c.png)
8. body部分が編集できるようになるので、taskRelativePath、client、userを編集して「Execute」ボタンを押します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/7ee21a49-0a18-f165-1b5f-5e6942746297.png)<br/>taskRelativePathには、Control Roomで対象のBotの詳細画面を表示させて依存関係の下に表示されるパスの「Automation Anywhere\...」に続く部分 ("`My Tasks\Messagebox.atmx`") を抜き出して、"`\`"は"`\\`"として指定します (つまり "`My Tasks\\Messagebox.atmx`")。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/39f8af99-9f66-1e80-eed1-45143618eb30.png)<br/>clientとuserには、Control Roomの「デバイス」一覧で表示されているUnattended Bot Runnerのデバイスのものを指定します。<br/>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/4ddd2c60-ec0d-68ea-53e5-ebc2d2106162.png)

正常に実行されると、しばらくして指定されたデバイスのEnterprise Client上でBotが実行されます。


### エラーコード/エラーメッセージ
実行するにあたって遭遇したエラーと回避策を書いておきます。これ、この粒度ではどこにも記載がなく、苦労しました。。。

|エラーコード|メッセージ|状況と回避策|
|:--|:--|:--|
|400|**Error: Bad Request**<br/> "code": "json.deserialization.exception",<br/>"details": null,<br/>"message": "Invalid request parameters"|文法が間違っている。区切り文字が "`\\`"でなく"`\`"になっている可能性など|
|400|**Error: Bad Request**<br/>"message": "Incorrect relative path name"|文法はあっているが指定された相対パスの場所にファイルがない|
|400|**Error: Bad Request**<br/>"message": "No audit context"|userに指定されているアカウントが存在しないかUnattended Bot Runner権限を持っていない (APIを呼ぶユーザーと同一である必要はない)|
|400|**Error: Bad Request**<br/>"message": "Invalid devices [デバイス名]"|clientに指定されたデバイスがuserでサインインされていない。clientのEnterprise Clientはuserに指定されたユーザーでサインインしておく|
|401|**Error: Unauthorized**<br/>"code": "UM1110",<br/>"details": "This may be due to a misspelling or because your Caps Lock is on. To continue, please retype your username and password.",<br/>"message": "Either your username or your password is incorrect"|指定したユーザー名かパスワードが間違っている|
|401|**Error: Unauthorized**<br/>"code": "UM1117",<br/>"details": null,<br/>"message": "Access token expected in the 'X-Authorization' header"|APIを呼ぶ際にサインインがされていない|
|401|**Error: Unauthorized**<br/>"code": "UM9999",<br/>  "details": null,<br/>  "message": "An unexpected problem occurred."|指定したapiKeyが正しくないか、期限が切れている|
|403|**Error:Forbidden**<br/>"message": "You no longer have permissions to run bot"|APIを呼んだユーザーがControl RoomからBotを実行する権限を持っていない。権限を付与するか他のユーザーでAPIにサインインして実行する|
|404|**Error:Not Found**<br/>"message": "Device not found"|clientに指定されたデバイスが存在しない|

正常に終了すると以下が返ります。

|コード|メッセージ|
|:--|:--|
|200|"deploymentFailOn": [],<br/>"message": "Task '(タスク名)' deployed successfully on selected client(s)."|



# curlとバッチファイルを使ってローカルPCからの実行を実装してみる
Swagger UIの操作中に、同等の操作をコマンドラインからcurlを使って行う文法が表示されています。これをコピペしてバッチファイルに仕込むと、ローカルPCから一発のダブルクリックでBotを実行することができます。

今回の操作をまとめると以下のファイルとなります。

```:Automate.cmd
@SET crurl=%~1
@SET username=%~2
@SET password=%~3
@SET taskRelativePath=%~4
@SET client=%~5
@SET user=%~6
@curl -s -X POST "%crurl%/v1/authentication" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"username\": \"%username%\", \"password\": \"%password%\"}" | jq-win64 -r .token > %TMP%\tmp.txt
@SET /p token=<%TMP%\tmp.txt
@DEL %TMP%\tmp.txt
@curl -s -X POST "%crurl%/v1/schedule/automations/deploy" -H "accept: application/json" -H "X-Authorization: %token%" -H "Content-Type: application/json" -d "{ \"taskRelativePath\": \"%taskRelativePath%\", \"botRunners\": [ { \"client\": \"%client%\", \"user\": \"%user%\" } ], \"runWithRDP\": true}"
@pause
```

コマンドラインから以下のように引数を付けて呼び出します。
`Automate.cmd (Control Room URL) (username) (password) (taskRelativePath) (client) (user)`

メモ

* コマンドライン引数に`%~1`などの「チルダ」を付けると、引数全体が引用符で囲われている場合は引用符が削除されたものを参照します。
* Swagger UIで生成されるcurlコマンドにサイレントオプション`-s`を付けています。
* jq-win64にはcurlコマンドからパイプでJSONを渡します。`-r`オプションを付けると外側で囲っている引用符が削除されたものを返します。
* コマンドプロンプトでは、標準出力 (stdout)の内容を変数に直接代入できないため、一旦一時ファイル ("`%TMP%\tmp.txt`")に結果を出力して、そのファイルの内容を次の行の`SET /p`コマンドで変数に代入します。

Automate.cmdを実行すると、正常に実行されると指定したBotが起動します。


#まとめ
Bot CreatorによるBotのローカル実行に相当することをUnattended Bot RunnerでもAPI経由で実行できることが確認できました！サーバー型RPAとしてのBot実行の様式を、API経由で試してみてください。