With your node Collect.RevitLinks, how can I get an extra output for the link document ??
(currently outputs linkType and linkInstances)
i.e similar to an old Archi-lab node ‘Get Documents’
thanks
Andrew
With your node Collect.RevitLinks, how can I get an extra output for the link document ??
(currently outputs linkType and linkInstances)
i.e similar to an old Archi-lab node ‘Get Documents’
thanks
Andrew
Use the Revit.GetDocument node. That will get the document for a link instance.
I also have a similar node called Revit.GetDocuments which also rounds up documents that are not active in addition.
Hi @GavinNicholls
thanks for the fast reply
What if I need both the LinkInstance plus the doc ??
Reason being- I want to get the ACC attributes and push them into the linkInstance parameters
I wounder if this might be easier to find via the TransmissionData class… Not sure how that manages cloud paths, though I assume it would have to have both the project and model GUIDs.
What is the reasoning for pushing those GUIDs into the link?
ACC documents will be a bit different I think, but the link would still be parallel to the document it represents as an output. Noting I do deal with the raw DB Document output type.
You can’t push data into a linked document instance to my understanding, it’s not like a live document. You have to programmatically open the document itself and set the data in there unless I’m misunderstanding your task. I’d look into Dynamo multiplayer for that.
If you mean as a shared parameter on the link instance object, that should work as is I guess. Pull the data out of the link instance’s doc, then set it to its project parameters at the host document level.
thanks @jacob.small & @GavinNicholls
It might help to explain what i’m trying to achieve.
For big projects with many models, there is (model level) data in ACC which is useful, such as:
model description
last modified date
ACC path
etc
You can’t see any of that data in Revit, unless you backtrack from Revit (using the link name, or the path from ‘manage links’)
So the logic is:
Andrew
I think once you hit the ‘from acc’ part, dynamo is limited. My understanding is APS/forge is needed for that type of query but happy to be proven wrong.
So your missing a few steps in the workflow. For now let’s ignore the Dynamo bit and focus on the steps you will have to take by hand to get this info. One thing to note, there is no such thing as a ‘path’ in APS. All things including cloud models, files, and folders are just objects in the project.
Alternatively for steps 7-9 can just extract the web link to the model’s parent folder and have the user click that to go there (assuming they have access rights).
Sadly steps 1-10 (or 1-8) involve two application APIs - Revit and Autodesk Construction Cloud via Aurodesk Platform Services. The former you have already accomplished to some degree and I know you’re capable and familiar with in the context of Dynamo. However it could also be done via Python, Macro, Add-In, or even Design Automation using APS. The later requires using some web development skills, which also entails authenticating your user or your application. To complicate things further any time someone updates a property, moved a file on ACC, or changes a link path in Revit (so there are triggers in the desktop and the could environment) which make running this often or on trigger a must. That’s a problem for another day.
To build a Dynamo version of the APS tool is no small feat, though it also isn’t any harder than building it as a web app, macro, desktop tool, or Revit add-in. First learn how to manage what you are after on the web though. Tools like Postman can simplify the learning aspect as it allows calling APIs without requiring that you build the UI or work with a debugger to read results.
Perhaps more fortunately the APS aspect is simple and common enough that there are good tutorials for most of it.
Start here: https://get-started.aps.autodesk.com/
Then move onto here: Data Management API | Autodesk Platform Services (APS)
And finally build the toolset again in the automation method of your choice.
hi,
it’s necessary to get urn too, here is an example of how to obtain some datas from an link using APS.
import clr
import sys
import System
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
import traceback
import json
import urllib.request
import urllib.error
import json
import ssl
from base64 import b64encode
def get_auth_token(client_id, secret_id):
url = "https://developer.api.autodesk.com/authentication/v2/token"
client_credentials = f"{client_id}:{secret_id}"
b_64_pass = b64encode(client_credentials.encode("utf-8")).decode("utf-8")
#
token = None
payload = {
"grant_type": "client_credentials",
"scope": "data:read data:search" ,
}
#
json_data = urllib.parse.urlencode(payload).encode('utf-8')
# Create request with headers
request = urllib.request.Request(
url,
data=json_data,
headers={
"Authorization": "Basic {}".format(b_64_pass),
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
method='POST'
)
try:
# Send request
with urllib.request.urlopen(request) as response:
status_code = response.getcode()
response_data = json.loads(response.read().decode('utf-8'))
token_type = response_data["token_type"]
token = response_data["access_token"]
#
except urllib.error.HTTPError as e:
print(f"Status Code: {e.code}")
print(traceback.format_exc())
try:
error_data = json.loads(e.read().decode('utf-8'))
print(f"Response: {error_data}")
except:
print(f"Response: Error {e.code} - {e.reason}")
#
except Exception as e:
print(traceback.format_exc())
return token
def get_request_data_management(url):
global token
response_data = None
# Prepare headers
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json" }
# Build the request
request = urllib.request.Request(url, headers=headers, method='GET' )
try:
# Send request
with urllib.request.urlopen(request) as response:
resultA = response.read().decode('utf-8')
response_data = json.loads(resultA)
except urllib.error.HTTPError as e:
print(f"Status Code: {e.code}")
try:
error_data = json.loads(e.read().decode('utf-8'))
print(f"Response: {error_data}")
except:
print(f"Response: Error {e.code} - {e.reason}")
except Exception as e:
print(traceback.format_exc())
return response_data
#Preparing input from dynamo to revit
linkInstance = UnwrapElement(IN[0])
linkdoc = linkInstance.GetLinkDocument()
path = linkdoc.GetCloudModelPath()
model_urn = linkdoc.GetCloudModelUrn()
my_project_Guid = path.GetProjectGUID()
model_Guid = path.GetModelGUID()
data_link = {}
my_hub_name = "MY_HUB_NAME"
name_project_acc = "MY_PROJECT_NAME"
# get token
token_type = None
token = get_auth_token("CLIENT_ID_KEY", "CLIENT_SECRET_KEY")
jobject_hubs_data = get_request_data_management("https://developer.api.autodesk.com/project/v1/hubs/")
#
data_hubs_array = jobject_hubs_data["data"]
my_hub_id = next((data["id"] for data in data_hubs_array if data["attributes"]["name"] == my_hub_name), None)
#
# get project id
jobject_projects_data = get_request_data_management(f"https://developer.api.autodesk.com/project/v1/hubs/{my_hub_id}/projects")
data_array_projects = jobject_projects_data["data"]
my_project_id = next((data["id"] for data in data_array_projects if data["attributes"]["name"] == name_project_acc), None)
#
# get file info fom urn
jobject_versions = get_request_data_management(f"https://developer.api.autodesk.com/data/v1/projects/{my_project_id}/items/{model_urn}/versions")
data_versions_array = jobject_versions["data"]
for j_version in data_versions_array:
data_extension = j_version["attributes"]["extension"]["data"]
if data_extension["modelGuid"] == model_Guid.ToString():
data_link = j_version["attributes"]
break
OUT = data_link
I couldn’t get the ACC Id of the ACC project directly from the Revit API (only the urn of the model), if anyone has a more direct solution I’m interested.
edit, fixed, see the next post Crumple: Collect.RevitLinks - #11 by c.poupin
Resources:
Note
if you have the id (ACC) of the host model cloud, you can use this method to get RevitLinks
The Document
has the GetProjectId()
method. This appears to be from the Data Management API.
It is also possible to get additional ACC link information from the RevitLinkType
elements that doesn’t require the loading in of the documents - much faster
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
def get_ref_info(revit_link_type):
ref = next(iter(revit_link_type.GetExternalResourceReferences().Values))
return ref.GetReferenceInformation()
info_from_type = [
get_ref_info(rlt) for rlt in FilteredElementCollector(doc).OfClass(RevitLinkType)
]
OUT = info_from_type
Expurgated example
thanks, I’d overlooked it, so here’s the simplified example
import clr
import sys
import System
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
import traceback
import json
import urllib.request
import urllib.error
import json
import ssl
from base64 import b64encode
def get_auth_token(client_id, secret_id):
url = "https://developer.api.autodesk.com/authentication/v2/token"
client_credentials = f"{client_id}:{secret_id}"
b_64_pass = b64encode(client_credentials.encode("utf-8")).decode("utf-8")
#
token = None
payload = {
"grant_type": "client_credentials",
"scope": "data:read data:search" ,
}
#
json_data = urllib.parse.urlencode(payload).encode('utf-8')
# Create request with headers
request = urllib.request.Request(
url,
data=json_data,
headers={
"Authorization": "Basic {}".format(b_64_pass),
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
method='POST'
)
try:
# Send request
with urllib.request.urlopen(request) as response:
status_code = response.getcode()
response_data = json.loads(response.read().decode('utf-8'))
token_type = response_data["token_type"]
token = response_data["access_token"]
#
except urllib.error.HTTPError as e:
print(f"Status Code: {e.code}")
print(traceback.format_exc())
try:
error_data = json.loads(e.read().decode('utf-8'))
print(f"Response: {error_data}")
except:
print(f"Response: Error {e.code} - {e.reason}")
#
except Exception as e:
print(traceback.format_exc())
return token
def get_request_data_management(url):
global token
response_data = None
# Prepare headers
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json" }
# Build the request
request = urllib.request.Request(url, headers=headers, method='GET' )
try:
# Send request
with urllib.request.urlopen(request) as response:
resultA = response.read().decode('utf-8')
response_data = json.loads(resultA)
except urllib.error.HTTPError as e:
print(f"Status Code: {e.code}")
try:
error_data = json.loads(e.read().decode('utf-8'))
print(f"Response: {error_data}")
except:
print(f"Response: Error {e.code} - {e.reason}")
except Exception as e:
print(traceback.format_exc())
return response_data
#Preparing input from dynamo to revit
linkInstance = UnwrapElement(IN[0])
linkdoc = linkInstance.GetLinkDocument()
path = linkdoc.GetCloudModelPath()
model_urn = linkdoc.GetCloudModelUrn()
project_id = linkdoc.GetProjectId()
my_project_Guid = path.GetProjectGUID()
model_Guid = path.GetModelGUID()
data_link = {}
# get token
token_type = None
token = get_auth_token("CLIENT_ID_KEY", "CLIENT_SECRET_KEY")
#
# get file fom urn
jobject_versions = get_request_data_management(f"https://developer.api.autodesk.com/data/v1/projects/{project_id}/items/{model_urn}/versions")
data_versions_array = jobject_versions["data"]
for j_version in data_versions_array:
data_extension = j_version["attributes"]["extension"]["data"]
if data_extension["modelGuid"] == model_Guid.ToString():
data_link = j_version["attributes"]
break
OUT = data_link
A bit out of the scope of the thread - if you have access to the Data Model API, GraphQL absolutely rips! Currently using with Postman - only need the project urn
query ElementGroupsByProject($projectId: ID!) {
elementGroupsByProject(projectId: $projectId) {
results {
id
name
lastModifiedOn
version {
versionNumber
createdOn
}
}
}
}
Result with id’s removed