Skip to content

Commit

Permalink
Add model caching
Browse files Browse the repository at this point in the history
  • Loading branch information
adamenagy committed May 7, 2020
1 parent 7b0f563 commit 2f54008
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 39 deletions.
179 changes: 149 additions & 30 deletions forgesample/Controllers/DesignAutomationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
using Parameter = Autodesk.Forge.DesignAutomation.Model.Parameter;
using WorkItem = Autodesk.Forge.DesignAutomation.Model.WorkItem;
using WorkItemStatus = Autodesk.Forge.DesignAutomation.Model.WorkItemStatus;
using System.Security.Cryptography;
using System.Text;


namespace forgeSample.Controllers
Expand Down Expand Up @@ -109,8 +111,18 @@ public static string Base64Encode(string plainText)
return System.Convert.ToBase64String(plainTextBytes);
}

public static string MD5Encode(JObject obj)
{
using (MD5 md5 = MD5.Create())
{
md5.Initialize();
md5.ComputeHash(Encoding.UTF8.GetBytes(obj.ToString(Formatting.None)));
return BitConverter.ToString(md5.Hash).Replace("-", "");
}
}

/// <summary>
/// Define a new appbundle
/// Upload sample files
/// </summary>
[HttpPost]
[Route("api/forge/designautomation/files")]
Expand Down Expand Up @@ -150,33 +162,66 @@ public async Task<IActionResult> UploadOssFiles([FromBody]JObject appBundleSpecs
{
dynamic res = await objects.UploadObjectAsync(BucketKey, fileName, (int)streamReader.BaseStream.Length, streamReader.BaseStream, "application/octet-stream");

// prepare the payload
List<JobPayloadItem> outputs = new List<JobPayloadItem>()
{
new JobPayloadItem(
JobPayloadItem.TypeEnum.Svf,
new List<JobPayloadItem.ViewsEnum>()
{
JobPayloadItem.ViewsEnum._2d,
JobPayloadItem.ViewsEnum._3d
}
)
};
JobPayload job;
string urn = Base64Encode(res.objectId);
job = new JobPayload(new JobPayloadInput(urn), new JobPayloadOutput(outputs));

// start the translation
DerivativesApi derivative = new DerivativesApi();
derivative.Configuration.AccessToken = oauth.access_token;

derivative.TranslateAsync(job);
TranslateFile(res.objectId, null);
}
}

return Ok();
}

private async Task TranslateFile(string objectId, string rootFileName)
{
dynamic oauth = await OAuthController.GetInternalAsync();

// prepare the payload
List<JobPayloadItem> outputs = new List<JobPayloadItem>()
{
new JobPayloadItem(
JobPayloadItem.TypeEnum.Svf,
new List<JobPayloadItem.ViewsEnum>()
{
JobPayloadItem.ViewsEnum._2d,
JobPayloadItem.ViewsEnum._3d
}
)
};
JobPayload job;
string urn = Base64Encode(objectId);
if (rootFileName != null)
{
job = new JobPayload(new JobPayloadInput(urn, true, rootFileName), new JobPayloadOutput(outputs));
}
else
{
job = new JobPayload(new JobPayloadInput(urn), new JobPayloadOutput(outputs));
}

// start the translation
DerivativesApi derivative = new DerivativesApi();
derivative.Configuration.AccessToken = oauth.access_token;

await derivative.TranslateAsync(job);
}

/// <summary>
/// Get files in bucket
/// </summary>
[HttpGet]
[Route("api/forge/designautomation/files")]
public async Task<IActionResult> GetOssFiles()
{
System.Diagnostics.Debug.WriteLine("GetOssFiles");
// OAuth token
dynamic oauth = await OAuthController.GetInternalAsync();

ObjectsApi objects = new ObjectsApi();
objects.Configuration.AccessToken = oauth.access_token;

dynamic res = await objects.GetObjectsAsync(BucketKey);

return Ok(res);
}

/// <summary>
/// Define a new appbundle
/// </summary>
Expand Down Expand Up @@ -296,6 +341,24 @@ public async Task<IActionResult> CreateActivity([FromBody]JObject activitySpecs)
return Ok(new { Activity = "Activity already defined" });
}

/// <summary>
/// Define a new activity
/// </summary>
public static async Task<bool> IsInCache(string fileName)
{
dynamic oauth = await OAuthController.GetInternalAsync();
ObjectsApi objects = new ObjectsApi();
objects.Configuration.AccessToken = oauth.access_token;

try
{
dynamic res = await objects.GetObjectDetailsAsync (BucketKey, fileName);
return true;
} catch {}

return false;
}

/// <summary>
/// Start a new workitem
/// </summary>
Expand All @@ -305,12 +368,16 @@ public async Task<IActionResult> StartWorkitems([FromBody]JObject input)
{
System.Diagnostics.Debug.WriteLine("StartWorkitem");
string browerConnectionId = input["browerConnectionId"].Value<string>();
bool useCache = input["useCache"].Value<bool>();
string pngWorkItemId = "skipped";
string jsonWorkItemId = "skipped";
string zipWorkItemId = "skipped";

// OAuth token
dynamic oauth = await OAuthController.GetInternalAsync();

string pngFileName = browerConnectionId + ".png";
string pngWorkItemId = await CreateWorkItem(
pngWorkItemId = await CreateWorkItem(
input,
new Dictionary<string, string>() { { "Authorization", "Bearer " + oauth.access_token } },
browerConnectionId,
Expand All @@ -319,8 +386,48 @@ public async Task<IActionResult> StartWorkitems([FromBody]JObject input)
string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", BucketKey, pngFileName)
);

if (useCache) {
string hash = MD5Encode(input["params"] as JObject);
string zipFileName = hash + ".zip";
double [] cells = new double [] {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
if (await IsInCache(zipFileName))
{
JObject data = new JObject(
new JProperty("components",
new JArray(
new JObject(
new JProperty("fileName", zipFileName),
new JProperty("cells", cells)
)
)
)
);
await SendComponentsDataToClient(browerConnectionId, data);

return Ok(new {
PngWorkItemId = pngWorkItemId,
JsonWorkItemId = jsonWorkItemId,
ZipWorkItemId = zipWorkItemId
});
} else {
zipWorkItemId = await CreateWorkItem(
input,
new Dictionary<string, string>() { { "Authorization", "Bearer " + oauth.access_token } },
browerConnectionId,
"outputZip",
zipFileName,
string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", BucketKey, zipFileName)
);
}
}

string jsonFileName = browerConnectionId + ".json";
string jsonWorkItemId = await CreateWorkItem(
jsonWorkItemId = await CreateWorkItem(
input,
new Dictionary<string, string>() { { "Content-Type", "application/json" } },
browerConnectionId,
Expand All @@ -330,8 +437,9 @@ public async Task<IActionResult> StartWorkitems([FromBody]JObject input)
);

return Ok(new {
PngWorkItemId = "pngWorkItemId",
JsonWorkItemId = "jsonWorkItemId"
PngWorkItemId = pngWorkItemId,
JsonWorkItemId = jsonWorkItemId,
ZipWorkItemId = zipWorkItemId
});
}
private async Task<string> CreateWorkItem(JObject input, Dictionary<string, string> headers, string browerConnectionId, string outputName, string fileName, string url)
Expand Down Expand Up @@ -370,6 +478,12 @@ private async Task<string> CreateWorkItem(JObject input, Dictionary<string, stri
return workItemStatus.Id;
}

private async Task SendComponentsDataToClient(string id, JObject data)
{
data["urnBase"] = "urn:adsk.objects:os.object:" + BucketKey + "/";
await _hubContext.Clients.Client(id).SendAsync("onComponents", data.ToString(Formatting.None));
}

/// <summary>
/// Define a new appbundle
/// test with curl:
Expand All @@ -379,13 +493,12 @@ private async Task<string> CreateWorkItem(JObject input, Dictionary<string, stri
/// </summary>
[HttpPut]
[Route("api/forge/callback/ondata/json")]
public async Task<IActionResult> OnData([FromRoute] string dataType, [FromQuery] string id, [FromBody] JObject data)
public async Task<IActionResult> OnData([FromQuery] string id, [FromBody] JObject data)
{
System.Diagnostics.Debug.WriteLine("OnData, dataType = " + dataType);
System.Diagnostics.Debug.WriteLine("OnData");

// urnBase, something like "urn:adsk.objects:os.object:rgm0mo9jvssd2ybedk9mrtxqtwsa61y0-designautomation/"
data["urnBase"] = "urn:adsk.objects:os.object:" + BucketKey + "/";
await _hubContext.Clients.Client(id).SendAsync("onComponents", data.ToString(Formatting.None));
await SendComponentsDataToClient(id, data);

return Ok();
}
Expand Down Expand Up @@ -419,6 +532,12 @@ public async Task<IActionResult> OnComplete(string id, string outputFile, [FromB
dynamic signedUrl = await objects.CreateSignedResourceAsyncWithHttpInfo(BucketKey, outputFile, new PostBucketsSigned(10), "read");
await _hubContext.Clients.Client(id).SendAsync("onPicture", (string)(signedUrl.Data.signedUrl));
}

if (outputFile.EndsWith(".zip"))
{
string objectId = "urn:adsk.objects:os.object:" + BucketKey + "/" + outputFile;
TranslateFile(objectId, "shelves.iam");
}
}
catch (Exception e)
{
Expand Down
30 changes: 25 additions & 5 deletions forgesample/wwwroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<script src="/js/ForgeViewer.js"></script>
<style>
#outputlog {
height: calc(100vh - 435px);
height: calc(100vh - 475px);
}
#forgeViewer {
height: 100%;
Expand All @@ -41,6 +41,12 @@
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
display: none;
}
#showConfigureDialog {
float: right;
margin-top: 15px;
cursor: pointer;
display: none;
}

.previewImage {
display:block;
Expand Down Expand Up @@ -95,9 +101,15 @@
</a>
</li>
</ul>
<div style="float: right; margin-top: 15px; cursor: pointer; display: none;" id="showConfigureDialog">
<span style="padding-right: 5px;" data-toggle="modal" data-target="#defineActivityModal" title="Configure AppBundle, Activity and upload sample files"><span
class="glyphicon glyphicon-cog glyphiconTop mlink"> </span> Configure</span>
<div id="showConfigureDialog">
<span
style="padding-right: 5px;"
data-toggle="modal"
data-target="#defineActivityModal"
title="Configure AppBundle, Activity and upload sample files">
<span class="glyphicon glyphicon-cog glyphiconTop mlink"></span>
Configure
</span>
</div>
</div>
</nav>
Expand Down Expand Up @@ -132,7 +144,15 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" id="hideLoading" required>
<label class="form-check-label" for="hideLoading">
Hide loading in Viewer
Show preview while model is loading in Viewer
</label>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="useCache" required>
<label class="form-check-label" for="useCache">
Use cache for storing and loading models
</label>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions forgesample/wwwroot/js/ForgeDesignAutomation.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,26 @@ function uploadSourceFiles(cb) {

function showProgressIcon(show) {
$("#progressIcon").css('display', (show) ? 'block' : 'none')
$("#startWorkitem").prop('disabled', show)
}

function startWorkitem() {
showProgressIcon(true)

let useCache = $("#useCache").is(":checked")
let width = Math.floor($("#forgeViewer").width())
let height = Math.floor($("#forgeViewer").height())
var data = {
browerConnectionId: connectionId,
useCache: useCache,
params: {
height: `\"${$("#height").val()}\"`,
shelfWidth: `\"${$("#shelfWidth").val()}\"`,
numberOfColumns: `${$("#numberOfColumns").val()}`
},
screenshot: {
width: width,
height: height,
position: [10, 10, 10],
target: [0, 0, 0],
up: [0, 0, 1]
height: height
}
};
writeLog(data);
Expand Down

0 comments on commit 2f54008

Please sign in to comment.