I am integrating between Design automation and BIM 360 API in autodesk forge
I call step 7 Design automation
https://forge.autodesk.com/en/docs/design-automation/v3/tutorials/revit/step7-post-workitem/
{
"activityId": "YOUR_NICKNAME.DeleteWallsActivity+test",
"arguments": {
"rvtFile": {
"url": "SIGNED_URL_TO_INPUT_FILE",
"pathInZip": "PATH_TO_RVT_FILE_WITHIN_ZIP_FILE"
},
"result": {
"verb": "put",
"url": "SIGNED_URL_TO_RESULT"
}
}
}'
The param rvtFile.(url), i binding link download file by step 5 in Bim 360 Document
https://forge.autodesk.com/en/docs/bim360/v1/tutorials/document-management/download-document/
{
"activityId": "cbbdemo.DemoTestingActivity43+test",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt",
"localName": "testing.rvt",
},
"params": {
"url": "data:application/json,{'action' : 'generate','scaffoldName' : 'SM0918', 'space' : 300,'isGenFront' : true,'data' : ['138763','138533']}"
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/signedresources/fbe64c4f-1073-49a7-810b-95658e51b361?region=US"
}
}
}
But when download file revit by API Bim 360 is failed because need token Authorization
So is there a way to download files from bim 360 without tokens?
Unfortunately, you cannot call the OSS API https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt without passing an access token.
The solution is to use a Signed URL to download the file, but since you're not the owner of the bucket wip.dm.prod. It's owned by BIM360 or ACC service itself. So you cannot create Signed URLs for objects stored on the wip.dm.prod bucket. So, at this moment, please pass a valid access token like the one below:
{
"activityId": "cbbdemo.DemoTestingActivity43+test",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt",
"localName": "testing.rvt",
"headers": {
"Authorization": "Bearer {{Bearer}}",
"Content-Type": "application/octet-stream"
}
},
"params": {
"url": "data:application/json,{'action' : 'generate','scaffoldName' : 'SM0918', 'space' : 300,'isGenFront' : true,'data' : ['138763','138533']}"
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/signedresources/fbe64c4f-1073-49a7-810b-95658e51b361?region=US"
}
}
}
Related
I have implemented a viewer using Autodesk Platform Services (former name Forge) on .NET Core. In the bucket I upload 2D drawings in .dwg format.
I enabled the markup feature in the viewer, so now I can make any markup on top of the .dwg
What I have for the moment looks like this:
I need to save this dwg with the markups I did, and either have it as a 2nd dwg inside the bucket or to override the original one.
The steps I have taken until now:
In javascript behind I can get the markups only as .svg format using the .generateData() on the MarkupsCore extension:
const markupCore = await viewer.loadExtension('Autodesk.Viewing.MarkupsCore');
let svgMarkup = markupCore.generateData();
After getting the svg mark up, I convert it in .dxf file.
I think I need to use the Design Automation API to import this dxf file into the dwg,
but I don't know how to handle this.
I have checked the following link on importing dxf into dwg but so far I can't find something for my case.
AutoDesk Design Automation tutorials on autocad
In case someone knows maybe another way on handling this, please let me know.
I think I need to use the Design Automation API to import this dxf file into the dwg, but I don't know how to handle this.
Yes that is correct, you may insert the dxf into the main drawing, you should be knowing scaling and position, so that will placed correctly on top your drawing.
Activity
{
"id": "{{ _.activityId }}",
"commandLine": [
"$(engine.path)\\accoreconsole.exe /i \"$(args[main].path)\" /s $(settings[script].path)"
],
"parameters": {
"main": {
"verb": "get",
"description": "test",
"required": true,
"localName": "$(inputFile)"
},
"overlay": {
"verb": "get",
"description": "",
"required": true,
"localName": "markups.dxf"
},
"result": {
"verb": "put",
"description": "",
"required": true,
"localName": "result.dwg"
}
},
"engine": "Autodesk.AutoCAD+24_1",
"description": "import markups",
"settings": {
"script": "-insert\nmarkups.dxf\n4,1,0\n1\n1\n0\nsaveas\n2018\nresult.dwg\n"
}
}
WorkiItem
{
"activityId": "{{ _.nickName }}.{{ _.activityId }}+{{ _.alias }}",
"arguments": {
"main": {
"url": "urn:adsk.objects:os.object:madlybuckets/main.dwg",
"verb": "get",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"overlay": {
"url": "urn:adsk.objects:os.object:madlybuckets/markups.dxf",
"verb": "get",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"result": {
"verb": "put",
"url": "urn:adsk.objects:os.object:madlybuckets/result.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
}
}
}
Here the main.dwg, markups.dxf is uploaded to APS Object Storage Service so that I can directly use object id of uploaded files instead of passing the object URL to the workitem.
How to programmatically create a new DWG file and load an existing DWG model into it using Autodesk Design Automation API for AutoCAD?
I am working on a project that requires me to automate the process of creating a new DWG file in AutoCAD and then load an existing DWG model into it using Autodesk Design Automation API. The goal is to automate the entire process without any manual intervention.
I am facing some difficulties in implementing the steps required to create a new DWG file and load an existing DWG model into it.
Can anyone provide a sample code or a detailed step-by-step explanation of how to programmatically create a new DWG file and load an existing DWG model into it using Autodesk Design Automation API for AutoCAD 2022? It would be great if the solution includes the necessary methods and properties to be used from the Autodesk Design Automation API.
I would highly appreciate any help or guidance in this matter.
input model dwg file
We have this ball valve model as input , we want to create a new dwg file add page border and load this existing dwg model inside page border using design automation api.
Expected Output :
expected output dwg file
I would encourage you to go through this tutorial https://tutorials.autodesk.io/tutorials/design-automation/, your objective should possible, you need to launch accoreconsole instance with your border drawing and insert the block from other drawing.
You can wrap the logic of importing blocks from external drawing in custom command .
Refer https://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html
Below is an example activty that importas "Microwave" block from "blocks.dwg" and inserts in "border.dwg"
Activity:
{
"id": "{{ _.activityId }}",
"commandLine": [
"$(engine.path)\\accoreconsole.exe \"$(args[main].path)\" /s $(settings[script].path)"
],
"parameters": {
"main": {
"verb": "get",
"description": "Main drawing to be loaded into AutoCAD.",
"required": true,
"localName": "border.dwg"
},
"blocks": {
"verb": "get",
"description": "The drawing which contains the blocks",
"required": true,
"localName": "blocks.dwg"
},
"BlockName": {
"verb": "read",
"description": "The block name to insert.",
"required": true
},
"BlockPosition": {
"verb": "read",
"description": "The position to insert block"
},
"ScaleX": {
"verb": "read",
"description": "The X scale factor",
"required": true
},
"ScaleY": {
"verb": "read",
"description": "The Y scale factor",
"required": true
},
"Rotation": {
"verb": "read",
"description": "The rotation angle of block",
"required": true
},
"result": {
"verb": "put",
"description": "",
"required": true,
"localName": "result.dwg"
}
},
"engine": "Autodesk.AutoCAD+23_1",
"description": "blah",
"settings": {
"script": "ImportBlocks\n"$(args[BlockName].value)\"\n\"$(args[BlockPosition].value)\"\n\"$(args[ScaleX].value)\"\n\"$(args[ScaleX].value)\"\n\"$(args[ScaleY].value)\"\n\"$(args[Rotation].value)\"\n_SAVEAS\n2018\nresult.dwg\n"
}
}
Workitem
{
"activityId": "{{ _.nickName }}.{{ _.activityId }}+{{ _.alias }}",
"arguments": {
"main": {
"verb": "get",
"url": "urn:adsk.objects:os.object:madlybuckets/main.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"blocks": {
"verb": "get",
"url": "urn:adsk.objects:os.object:madlybuckets/blocks.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"BlockName": "Microwave",
"BlockPosition": "198.241 162.455 0.0",
"ScaleX": "1.0",
"ScaleY": "1.0",
"Rotation": "0.0",
"result": {
"verb": "put",
"url": "urn:adsk.objects:os.object:madlybuckets/result.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
}
}
}
}
According to Forge API Reference, there is a workflowAttribute available to 'set some custom workflow information'. Its part of the misc object in the Body Structure of the POST request used to submit a job.
I am using the following request:
convertResponse = await axios({
method: "post",
url:
"https://developer.api.autodesk.com/modelderivative/v2/designdata/job",
headers: {
"Content-Type": "application/json",
Authorization: access_token
},
data: JSON.stringify({
input: { urn: url_safe_encoded_urn },
output: {
destination: { region: "us" },
formats: [
{
type: "svf",
views: ["2d", "3d"],
advanced: { generateMasterViews: true }
}
]
},
misc: {
workflow: "designgen-forge",
workflowAttribute: { projectId }
}
})
});
But when the webHook calls my callback function, I see nothing like hookAttribute available in the data:
{
"version": "1.0",
"resourceUrn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6c3VmZm9say1nZW5kZXNpZ25sb3ZlLWRldi10ZW1wLzkxZjhhNGZmLTM5NTYtNGM5Yi05NzkyLThiMWMxNDQyZGJkNyUyRnJldml0LTkxZjhhNGZmLTM5NTYtNGM5Yi05NzkyLThiMWMxNDQyZGJkNy5ydnQ",
"hook": {
"hookId": "6d770063-d5dc-4c66-8ed8-e84207ade07d",
"tenant": "designgen-forge",
"callbackUrl": "https://bigchief.ngrok.io/dev/workitemcomplete",
"createdBy": "9DqOEPqAd4ZZYQ2MAxuT2VQwMfAJrBGp",
"event": "extraction.updated",
"createdDate": "2020-10-20T20:14:31.874+0000",
"system": "derivative",
"creatorType": "Application",
"status": "active",
"scope": {
"workflow": "designgen-forge"
},
"urn": "urn:adsk.webhooks:events.hook:6d770063-d5dc-4c66-8ed8-e84207ade07d",
"__self__": "/systems/derivative/events/extraction.updated/hooks/6d770063-d5dc-4c66-8ed8-e84207ade07d"
},
"payload": {
"TimeStamp": 1603289180515,
"Env": "production",
"URN": "<my urn>",
"EventType": "UPDATED",
"Payload": {
"status": "inprogress",
"bubble": {
"guid": "<my guid>",
"owner": "<my guid>",
"hasThumbnail": "true",
"startedAt": "Wed Oct 21 14:05:39 UTC 2020",
"type": "design",
"urn": "<my urn>",
"success": "75%",
"progress": "50% complete",
"region": "US",
"status": "inprogress",
"children": []
},
"scope": "fd2d74bb-1d5a-407c-a344-20dffa327504",
"registerKey": []
}
}
}
I would imagine that is the intent of the workflowAttribute object to populate something in the callback data, otherwise, whats the point. Am I not specifying it correctly? Or is this not implemented? If not, webhooks become nearly unusable, I suppose the alternative is to make and destroy a webhook for each request, which is so ugly its not really a solution.
Thank you for bringing this to our attention. We could reproduce the issue as well - i.e. that the content of the workflowAttribute provided in the body of POST job request will not show up in the webhook callback.
It's being looked into, and I hope it will work soon, but I cannot yet provide a deadline for that.
In the meantime, the workaround could be either:
a) keep track of the extra data (in your case projectId) associated with the urn of the given file on the server or in a database (you might already be using one)
b) create separate webhooks, as you suggested, with different id for the "scope" -> "workflow" parameter and provide the data as the "hookAttribute" - that will show up in the callback
Update on 2020-12-14: it's working now - see https://forge.autodesk.com/blog/custom-data-translation-webhook
Making 2 and/or 3 legged auth request to Version/GetDownloads returns 400 when VersionId is valid and existing.
When trying to make an http call to a version's download endpoint (https://forge.autodesk.com/en/docs/data/v2/reference/http/projects-project_id-versions-version_id-downloads-GET/), the response returns:
{
"jsonapi": {
"version": "1.0"
},
"errors": [
{
"id": "a306d506-e374-4734-a68e-86c998fc7a5a",
"status": "400",
"code": "BAD_INPUT",
"title": "One or more input values in the request were bad",
"detail": "Request cannot be handled."
}
]
}
This would be ok if the Version Id didn't exist for the corresponding project, but requesting the version's download formats (https://forge.autodesk.com/en/docs/data/v2/reference/http/projects-project_id-versions-version_id-downloadFormats-GET/) returns a 200 response,
despite the version not having any download format:
{
"jsonapi": {
"version": "1.0"
},
"links": {
"self": {
"href": "https://developer.api.autodesk.com/data/v1/projects/{PROJECT_ID}/versions/{URN_VERSION_ID}/downloadFormats"
}
},
"data": {
"type": "downloadFormats",
"id": {URN_VERSION_ID},
"attributes": {
"formats": []
}
}
}
The file I am testing with is a pdf uploaded to BIM360 via the UI. I would have expected to get at least a 200 response on both endpoints. Also, I quite not understand why the downloadFormats endpoint does not return any format.
I have an application that submits work items to Design Automation for Revit (Design Automation v3 beta). Most of the work items submitted work fine, but some versions of the models appear to fail to parse the "rvtFile" argument. This then leads to the cloud Revit process failing to run because the file name argument is wrong.
Body of Activity POST:
{
"id": "ExtractModelCategoriesActivity",
"commandLine": ["$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"],
"parameters": {
"rvtFile": {
"zip": false,
"ondemand": false,
"verb": "get",
"description": "Input Revit model",
"required": true,
"localName": "$(rvtFile)"
},
"result": {
"zip": false,
"ondemand": false,
"verb": "put",
"description": "Model object categories by view",
"required": false,
"localName": "ModelCategories.json"
}
},
"engine": "Autodesk.Revit+2019",
"appbundles": ["alias_was_here.ExtractModelCategories+prod"],
"description": "Extract Model Categories to JSON Activity."
}
Body of Work Item POST:
{
"activityId": "alias_was_here.ExtractModelCategoriesActivity+prod",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/83b5eb1e-c9b7-4938-ad4e-8efc4789d0e2.rvt?scopes=b360project.22109894-5897-4aa9-96ab-2e3310bc4ae9,global,O2tenant.5952590",
"Headers": {
"Authorization": "Bearer token_was_here"
}
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/9dde6073-d490-4fd0-991e-4ff92af1957e.json",
"Headers": {
"Authorization": "Bearer token_was_here"
}
},
"onComplete": {
"verb": "post",
"url": "callback_url_was_here"
}
}
}
From the report.txt file for a successful submission:
[04/16/2019 12:03:50] Job information:
"CommandLine":[
"$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"
]
"Settings":{
"dasreportfailedlimits": {
"value": "true",
"isEnvironmentVariable": true
}
}
"Id":"e23918d475a74145aade32ba8968e5c3"
"ActivityId":"alias_was_here.ExtractModelCategoriesActivity+prod"
"Engine.Id":"Autodesk.Revit!21"
"Apps": [
"App.Id":"alias_was_here.ExtractModelCategories!1"
]
"BoundArguments":{
"rvtFile": {
"localName": "$(rvtFile)",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/839a11d8-51e9-42de-8936-28687feda65f.rvt?scopes=b360project.1949ed9d-e7fd-42b9-98f4-544fff3df42f,global,O2tenant.2971682",
"headers": {
"Authorization": "Bearer token_was_here"
}
},
"result": {
"localName": "ModelCategories.json",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/dd19b8f6-ac51-45b9-8f42-51c7c6a9d257.json",
"headers": {
"Authorization": "Bearer token_was_here"
},
"verb": "put"
},
"onComplete": {
"ondemand": true,
"optional": true,
"url": "callback_was_here",
"verb": "post"
},
"onProgress": {
"ondemand": true,
"url": "https://wlnr5sjl3a.execute-api.us-east-1.amazonaws.com/Prod/v3/workitems/progress",
"headers": {
"Content-Type": "application/json",
"x-das-authorize": "awssigv4(us-east-1)",
"x-ads-token-data": "{\"access_token\":{\"client_id\":\"alias_was_here\"},\"scope\":\"bucket:create bucket:read data:read data:create data:write code:all\",\"expires_in\":3595,\"client_id\":\"alias_was_here\"}",
"x-ads-developer-email": "email_was_here"
},
"verb": "put"
}
}
- snip -
[04/16/2019 12:03:57] ### Command line arguments: /isolate HKEY_CURRENT_USER\SOFTWARE\AppDataLow\Software\Autodesk\CoreUser\WorkItem_e23918d475a74145aade32ba8968e5c3 "T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\userdata" /exe "T:\Aces\AcesRoot\19.0\coreEngine\Exe\revitcoreconsole.exe" /i T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\839a11d8-51e9-42de-8936-28687feda65f.rvt /al T:\Aces\Applications\779cf68955e15ce6704c72a62c734afe.alias_was_here.ExtractModelCategories[1].package.
- snip -
[04/16/2019 12:03:57] Echoing command line args:
[04/16/2019 12:03:57] 0:/i
[04/16/2019 12:03:57] 1:T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\839a11d8-51e9-42de-8936-28687feda65f.rvt
- snip -
[04/16/2019 12:03:57] Running user application....
- snip -
[04/16/2019 12:04:22] Job finished with result Succeeded
[04/16/2019 12:04:22] Job Status:
{
"status": "success",
...
From the report.txt file for a failed submission:
[04/16/2019 12:04:44] Job information:
"CommandLine":[
"$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"
]
"Settings":{
"dasreportfailedlimits": {
"value": "true",
"isEnvironmentVariable": true
}
}
"Id":"4db3208a1c4e429c846c4da385f2219d"
"ActivityId":"alias_was_here.ExtractModelCategoriesActivity+prod"
"Engine.Id":"Autodesk.Revit!21"
"Apps": [
"App.Id":"alias_was_here.ExtractModelCategories!1"
]
"BoundArguments":{
"rvtFile": {
"localName": "$(rvtFile)",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/e597df42-07c7-41e1-aa0c-fa1abd179a4c.rvt?scopes=b360project.1949ed9d-e7fd-42b9-98f4-544fff3df42f,global,O2tenant.2971682",
"headers": {
"Authorization": "Bearer token was here"
}
},
"result": {
"localName": "ModelCategories.json",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/6b59f894-bbf0-421a-bf0b-e80d7584ee33.json",
"headers": {
"Authorization": "Bearer token_was_here"
},
"verb": "put"
},
"onComplete": {
"ondemand": true,
"optional": true,
"url": "callback_was_here",
"verb": "post"
},
"onProgress": {
"ondemand": true,
"url": "https://wlnr5sjl3a.execute-api.us-east-1.amazonaws.com/Prod/v3/workitems/progress",
"headers": {
"Content-Type": "application/json",
"x-das-authorize": "awssigv4(us-east-1)",
"x-ads-token-data": "{\"access_token\":{\"client_id\":\"alias_was_here\"},\"scope\":\"bucket:create bucket:read data:read data:create data:write code:all\",\"expires_in\":3596,\"client_id\":\"alias_was_here\"}",
"x-ads-developer-email": "email_was here"
},
"verb": "put"
}
}
- snip -
[04/16/2019 12:04:56] ### Command line arguments: /isolate HKEY_CURRENT_USER\SOFTWARE\AppDataLow\Software\Autodesk\CoreUser\WorkItem_4db3208a1c4e429c846c4da385f2219d "T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\userdata" /exe "T:\Aces\AcesRoot\19.0\coreEngine\Exe\revitcoreconsole.exe" /i T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile) /al T:\Aces\Applications\779cf68955e15ce6704c72a62c734afe.alias_was_here.ExtractModelCategories[1].package.
- snip -
[04/16/2019 12:04:56] Echoing command line args:
[04/16/2019 12:04:56] 0:/i
[04/16/2019 12:04:56] 1:T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile)
[04/16/2019 12:04:56] Running user application....
[04/16/2019 12:05:02] Exception: Revit input file not found: T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile)
- snip -
[04/16/2019 12:05:03] Job finished with result FailedExecution
[04/16/2019 12:05:03] Job Status:
{
"status": "failedInstructions",
...
As best I can tell, the format and structure of the body of both of the submissions is the same (these are version 10 and version 11 of the same model). However, for the failing work item, the Revit file name is not parsing and is still the string $(rvtFile) rather than the actual file name when DA processes the work item.
Any insight into the problem? Does the body of the submission have errors in it? How do I correct?
I am answering my own question based on what I have learned with the assistance of Zhong Wu with Autodesk:
This is currently an issue with the Design Automation for Revit API Beta. If the Revit model includes links to other models then the file downloaded to Design Automation is zipped and includes the main model and the linked file(s). Design Automation then fails because it expects a Revit file. This happens automatically on the API's side.
A work-around is to download the Revit file to another location utilizing the Data Management API. If the file provided by the Data Management API is a compressed file and not a Revit model, un-zip it. Then, place the uncompressed Revit file in a location accessible to Design Automation and post the work item referencing the location of the uncompressed file.
It is my understanding that a change request has been issued internally at Autodesk to improve the handling of compressed files. I have no timeline for this.
If I learn more, I will update this answer.
** UPDATE**
This was fixed by the Autodesk Forge team, and now runs for Revit files with links. Thank you!
Instead of using "localName": "$(rvtFile), could you use a static file name like "localName": "input.rvt"?