在上一篇文章中,我們講解了Forge Design Automation的基本原理和樣例程式碼的外掛部分。本文繼續前篇,當外掛包準備就緒後,轉向forgesample,基本框架流程是:
1 . app的Configure首先檢測本地可用的bundle壓縮包,即上篇文章編譯好的結果。選擇壓縮包,並選擇雲端Forge執行的引擎。顯然,Revit外掛的要Revit引擎。注意選擇合適的版本
2 . 點選【Create/Update】,app將從本地上傳bundle壓縮包到服務端,再透過Forge的雲端自動化服務埠建立自動化App,提交外掛包,建立Activity。所有這些準備好後,您的Forge賬戶中就含有了對應的Activity,而Activity連線到自動化App,知道使用哪個外掛執行接下來的任務。
/// <summary>
/// 建立雲端自動化app,上載外掛bundle
/// </summary>
[HttpPost]
[Route("api/forge/designautomation/appbundles")]
public async Task<IActionResult> CreateAppBundle([FromBody]JObject appBundleSpecs)
{
//......
/// <summary>
/// 建立 activity
/// </summary>
[HttpPost]
[Route("api/forge/designautomation/activities")]
public async Task<IActionResult> CreateActivity([FromBody]JObject activitySpecs)
{
//......
3 . 退出Configure視窗,程式會透過雲端自動化服務獲取Activity列表。在【Existing activities】選擇到需要的Activity
/// <summary>
/// 獲取該Forge賬戶下所有可用Activity列表
/// </summary>
[HttpGet]
[Route("api/forge/designautomation/activities")]
public async Task<List<string>> GetDefinedActivities()
{
Page<string> activities = await _designAutomation.GetActivitiesAsync();
//......
4 . 【Input File】選擇到本地的Revit檔案,可使用本例samples資料夾下提供的樣例檔案。
5 . 輸入需要改變的長和寬,點選[Start Workitem]. 將執行StartWorkitem
[HttpPost]
[Route("api/forge/designautomation/workitems")]
public async Task<IActionResult> StartWorkitem([FromForm]StartWorkitemInput input)
{
**StartWorkitem**首先把本地Revit上傳到後端,並透過Forge的Data Management API將檔案傳到某個bucket,和我們通常為了測試Forge Viewer上傳檔案到bucket一樣。因為Forge的雲端自動化服務的輸入檔案只能從雲端儲存而來,所以此案例利用Forge的bucket儲存。您也可以改造為從其它資料儲存。
``
//....
// 確保bucket存在,否則建立之
try
{
PostBucketsPayload bucketPayload = new PostBucketsPayload(bucketKey, null, PostBucketsPayload.PolicyKeyEnum.Transient);
await buckets.CreateBucketAsync(bucketPayload, "US");
}
catch { };
//.......
//上載檔案到bucket
using (StreamReader streamReader = new StreamReader(fileSavePath))
await objects.UploadObjectAsync(bucketKey, inputFileNameOSS, (int)streamReader.BaseStream.Length, streamReader.BaseStream, "application/octet-stream");
System.IO.File.Delete(fileSavePath);
當這些準備好以後,配置雲端自動化WorkItem的引數:
1) 輸入引數:一個是原始Revit檔案,透過配置access token來拿到
XrefTreeArgument inputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS),
Headers = new Dictionary<string, string>()
{
{ "Authorization", "Bearer " + oauth.access_token }
}
};
```
2) 需要更改的幾何資料(長寬),透過配置一個json檔案。長寬從客戶端提交的輸入而來。
dynamic inputJson = new JObject();
inputJson.Width = widthParam;
inputJson.Height = heigthParam;
XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
{
Url = "data:application/json, " + ((JObject)inputJson).ToString(Formatting.None).Replace("\"", "'")
};
3) 再配置更新後的Revit檔案放置的位置,同樣,本例將把結果檔案放回到bucket中。同樣,需要access token。
```
string outputFileNameOSS = string.Format("{0}_output_{1}",
DateTime.Now.ToString("yyyyMMddhhmmss"),
Path.GetFileName(input.inputFile.FileName));
XrefTreeArgument outputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}",
bucketKey, outputFileNameOSS),
Verb = Verb.Put,
Headers = new Dictionary<string, string>()
{
{"Authorization", "Bearer " + oauth.access_token }
}
};
```
4) 最後就是提交任務WorkItem,傳入前面配置好的引數,開啟雲端自動化的過程。
string callbackUrl = string.Format("{0}/api/forge/callback/designautomation?id={1}&outputFileName={2}",
OAuthController.GetAppSetting("FORGE_WEBHOOK_URL"), browerConnectionId,
outputFileNameOSS);
WorkItem workItemSpec = new WorkItem()
{
ActivityId = activityName,
Arguments = new Dictionary<string, IArgument>()
{
{ "inputFile", inputFileArgument },
{ "inputJson", inputJsonArgument },
{ "outputFile", outputFileArgument },
//回撥函式
{ "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } }
}
};
WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemsAsync(workItemSpec);
雲端自動化開啟後,需要一個過程才結束,可以透過主動查詢來獲取狀態,而本例採取回撥函式的方式,即onComplete。當WorkItem結束後,無論什麼情況,都自動通知callbackUrl, 帶上WorkItem執行的日誌(log)檔案內容。而callbackUrl定義如下:
[HttpPost]
[Route("/api/forge/callback/designautomation")]
public async Task<IActionResult> OnCallback(string id, string outputFileName, [FromBody]dynamic body)
{
由於預設是本地測試(localhost),回撥函式要得到響應,採取了ngrok做重定向。
但這只是通知了網路應用的後端,但怎麼自動通知前端瀏覽器呢?本例採用了SignalR. SignalR 是一個ASP .NET 下的類庫,可以在ASP .NET 的Web專案中實現實時通訊。此部分內容略過,請查閱本例的前後端相關程式碼。
當WorkItem成功執行,結果檔案匯出到Forge的bucket,還會提供一個簽名下載url,出現在客戶端皮膚,使用者就能把更改後的檔案下載來檢視了。
執行forgesample,按照Readme要求填寫Forge的client id,client secret,本網路應用的host,以及用於獲取Design Automation回撥結果狀態的ngrok 重定向連結。本文就不再贅述了。
本例可以作為研究其它方案的模板框架,只需要對前端使用者介面做一定修改,提供核心外掛模組,易於除錯和診斷Forge雲端自動化全過程。