Suite d'une introduction a l'API Autodesk Plateforme Service directement (APS) depuis Dynamo sur la plateforme ACC
#DynamoBIM #Revit #Python #APS #ACC #AutodeskExpertElite #AutodeskCommunity
if this article is not in your language, use the Google Translate
widget ⬈ (bottom of page for Mobile version ⬇)
- Introduction
1. Enregistrement et Authentification d'une Application Web :
- Comment enregistrer une application web et s'authentifier via une application tierce.
2. Gestion des Données de Projet :
- Localisation du dossier principal d'un projet sur ACC.
- Extraction et structuration des données des fichiers Revit en utilisant une DataTable avec .NET ou un DataFrame avec pandas.
- Technique pour lier des maquettes individuelles à une maquette hôte.
Nous utiliserons dans cet article les API suivantes
- Authentification API
- Data Management API
Dans la suite de cet article, nous utiliserons Dynamo3 + IronPython3 et la librairie .Net Newtonsoft Json.
Vous trouverez en fin d'article un exemple avec CPython3 et la libraire Python json
- Authentification et Scopes
Vous trouverez sur l'article précédent des informations sur l'authentification
Nous devons ici définir les 'scopes' suivant : data:read
/ data:search/ data:write
import sys
import clr
import System
from System.Collections.Generic import List, IList, Dictionary
import System.Text;
from System.Text import Encoding
clr.AddReference('Newtonsoft.Json')
import Newtonsoft.Json;
import Newtonsoft.Json.Linq;
from Newtonsoft.Json.Linq import JObject, JArray, JToken
clr.AddReference('System.Net.Http')
import System.Net.Http
from System.Net.Http import *
def get_auth_token(client_id, secret_id):
b_64_pass = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(client_id + ":" + secret_id))
token = None
with HttpClient() as client:
client.DefaultRequestHeaders.Add("Authorization", "Basic " + b_64_pass)
parameters = Dictionary[System.String, System.String]()
parameters.Add("Content-Type", "application/x-www-form-urlencoded")
parameters.Add("Accept", "application/x-www-form-urlencoded")
parameters.Add("grant_type", "client_credentials")
parameters.Add("scope", r"data:read data:write data:search")
response = client.PostAsync("https://developer.api.autodesk.com/authentication/v2/token", FormUrlEncodedContent(parameters)).Result
result = response.Content.ReadAsStringAsync().Result
jobject = JObject.Parse(result)
token_type = jobject["token_type"]
token = jobject["access_token"].ToString()
return token
token = get_auth_token("CLIENT_ID_KEY", "CLIENT_SECRET_KEY")
OUT = token
- Recherche du projet ACC sur notre Hub
Commençons par la localisation du projet dans Autodesk
Construction Cloud (ACC), en identifiant d'abord le hub puis le dossier
principal du projet.
import sys
import clr
import System
from System.Collections.Generic import List, IList, Dictionary
import System.Text;
from System.Text import Encoding
clr.AddReference('Newtonsoft.Json')
import Newtonsoft.Json;
import Newtonsoft.Json.Linq;
from Newtonsoft.Json.Linq import JObject, JArray, JToken
clr.AddReference('System.Net.Http')
import System.Net.Http
from System.Net.Http import *
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
def get_auth_token(client_id, secret_id):
b_64_pass = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(client_id + ":" + secret_id))
token = None
with HttpClient() as client:
client.DefaultRequestHeaders.Add("Authorization", "Basic " + b_64_pass)
parameters = Dictionary[System.String, System.String]()
parameters.Add("Content-Type", "application/x-www-form-urlencoded")
parameters.Add("Accept", "application/x-www-form-urlencoded")
parameters.Add("grant_type", "client_credentials")
parameters.Add("scope", r"data:read data:write data:search")
response = client.PostAsync("https://developer.api.autodesk.com/authentication/v2/token", FormUrlEncodedContent(parameters)).Result
result = response.Content.ReadAsStringAsync().Result
jobject = JObject.Parse(result)
token_type = jobject["token_type"]
token = jobject["access_token"].ToString()
return token
def get_request_data_management(url, main_item_id="", type_items_request =""):
global token
jobjectA = None
with HttpClient() as client:
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token)
response = client.GetAsync(url + main_item_id + type_items_request, HttpCompletionOption.ResponseContentRead).Result
resultA = response.Content.ReadAsStringAsync().Result
jobjectA = JObject.Parse(resultA)
#data_arrayA = JArray(jobjectA["data"])
return jobjectA
my_hub_name = "MY_HUB_NAME"
my_project_name = "MY_PROJECT_NAME"
# get token
token_type = None
token = get_auth_token("CLIENT_ID_KEY", "CLIENT_SECRET_KEY")
# get hub id
jobject_hubs_data = get_request_data_management("https://developer.api.autodesk.com/project/v1/hubs/")
data_hubs_array = JArray(jobject_hubs_data["data"])
my_hub_id = next((data["id"].ToString() for data in data_hubs_array if data["attributes"]["name"].ToString() == my_hub_name), None)
# get project id
jobject_projects_data = get_request_data_management("https://developer.api.autodesk.com/project/v1/hubs/", my_hub_id, type_items_request ="/projects")
data_array_projects = JArray(jobject_projects_data["data"])
my_project_id = next((data["id"].ToString() for data in data_array_projects if data["attributes"]["name"].ToString() == my_project_name), None)
# get root folder
root_folder_id = next((data["relationships"]["rootFolder"]["data"]["id"].ToString() for data in data_array_projects if data["attributes"]["name"].ToString() == my_project_name), None)
#
OUT = root_folder_id
- Récupérer les fichiers RVT ainsi que leurs propriétés
Dans le cadre de ce projet ACC, nous cherchons toutes les maquettes Revit et collectons quelques-unes de leurs propriétés.
Nous utilisons ici une fonction récursive avec une pause (time.sleep) pour ne pas dépasser le quota de requêtes autorisé.
Vous pouvez utiliser la fonction search si vous utilisez l'authentification en 3 étapes (3-Legged Token).
code complet (2 versions)
Si vous utilisez Dynamo, je recommande fortement d'utiliser un logger pour analyser les réponses des requêtes Web.
L'autre solution étant d'utiliser un notebook Jupiter ou Google Collab avec le module Python request
Vous pouvez utiliser la fonction search si vous utilisez l'authentification en 3 étapes (3-Legged Token).
code complet (2 versions)
Si vous utilisez Dynamo, je recommande fortement d'utiliser un logger pour analyser les réponses des requêtes Web.
L'autre solution étant d'utiliser un notebook Jupiter ou Google Collab avec le module Python request
- Liaison de modèles à une maquette
Dans ce dernier exemple, nous allons lier plusieurs maquettes à une maquette hôte, en se référant à cet article du blog APS.
Nous utilisons identifiants
uniques des modèles (URNs) recueillis à partir de la précédente DataTable (voir code précédent) pour
établir les liaisons des maquettes.
- Depuis la DataTable, nous isolons la maquette qui servira d'hôte et nous vérifions si elle comporte déjà des liens.
- Puis, nous effectuons des liaisons en récupérant les urns des maquettes les plus récentes.
Pour faire cela, nous utilisons pour cela le paramètrecopyFrom
de la méthode POST
projects/:project_id/versions
- fonction pour lier des modèles à un modèle hôte ACC
def post_request_link_files(projectId, mainfile_urn, lst_link_urn):
global token
response = None
with HttpClient() as client:
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token)
lst_xref = []
for link_urn in lst_link_urn:
lst_xref.append({
"type": "versions",
"id": link_urn,
"meta": {
"refType": "xrefs",
"direction": "from",
"extension": {
"type": "xrefs:autodesk.core:Xref",
"version": "1.1",
"data": {
"nestedType": "overlay"
}
}
}
})
content = {
"jsonapi": {
"version": "1.0"
},
"data": {
"type": "versions",
"relationships": {
"refs": {
"data": lst_xref
}
}
}
}
jsonRequest = Newtonsoft.Json.JsonConvert.SerializeObject(content);
httpContent = StringContent(jsonRequest, Encoding.UTF8, "application/json")
url = "https://developer.api.autodesk.com/data/v1/projects/{}/versions?copyFrom={}".format(projectId, mainfile_urn)
response = client.PostAsync(url, httpContent)
jsonResponse = response.Result.Content.ReadAsStringAsync().Result
#print(jsonResponse)
response_data = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonResponse);
return response_data
- code pour le processus de liaison
- filtrage de la DataTable
- vérification si la maquette contient déjà des liens
- appel de la fonction pour établir les liaisons avec les urns en arguments
Note
les caractères spéciaux présents dans les URL ("!*'();:@&=+$,/?%#[]") doivent être encodés.
# filter DataTable by Folder Name
strDataExpression = "[folder_name] = '"+ folder_rvt_models_to_federate + "'"
lstRows = dt.Select(strDataExpression)
# group by rvt name and order by version
lstRows = List[DataRow](lstRows \
.GroupBy(lambda r : r["file_name"]) \
.Select(lambda g : g.OrderBy( lambda r : int(r["version_number"])).Last()))
# convert DataRows to new Custom DataTable
newdt = CustomDataTable.DataRows_to_DataTable(lstRows, nameDataTable="RVT")
# get the host Revit model with "00" in rvt file name
filterFunc_Elec = System.Func[DataRow, System.Boolean](lambda row : row["file_name"].startswith("00"))
dataRows_Elec = Enumerable.Where[DataRow]([x for x in newdt.Rows], filterFunc_Elec )
# get the link Revit models with NOT "00" in rvt file name
filterFunc_link = System.Func[DataRow, System.Boolean](lambda row : not row["file_name"].startswith("00"))
dataRows_links = Enumerable.Where[DataRow]([x for x in newdt.Rows], filterFunc_link )
for row_elec in dataRows_Elec:
urn_id_version_main = row_elec["urn_id_version"]
# check if there are already relationships
jobject_relationships_data = get_request_data_management("https://developer.api.autodesk.com/data/v1/projects/",
my_project_id,
type_items_request ="/versions/{}/relationships/refs".format(HttpUtility.UrlEncode(urn_id_version_main)))
data_array_relationships = JArray(jobject_relationships_data["data"])
#
if len(data_array_relationships) == 0:
lst_link_urn_id_version = [r["urn_id_version"] for r in dataRows_links]
result = post_request_link_files(my_project_id, HttpUtility.UrlEncode(urn_id_version_main), lst_link_urn_id_version)
Quelques Ressources
- https://aps.autodesk.com/blog
- https://aps.autodesk.com/blog/bim360-docs-setting-external-references-between-files-upload-linked-files
- https://github.com/chuongmep/aps-toolkit
- https://github.com/chuongmep/aps-bot
- https://www.linkedin.com/posts/paolo-pozzoli-9bb5a183_autodesk-constructioncloud-bim360-activity-7199543266449522689-icbk?utm_source=share&utm_medium=member_desktop
0 commentaires:
Enregistrer un commentaire