Petite introduction a l'API Autodesk Plateforme Service directement (APS) depuis Dynamo (sur la plateforme ACC)
#DynamoBIM #Revit #Python #ACC #APS
#AutodeskExpertElite #AutodeskCommunity
if this article is not in your language, use the Google Translate
widget ⬈ (bottom of page for Mobile version ⬇)
Dans cet article, à l'aide d'APS, nous verrons :
- comment enregistrer une WEB Application
- comment s'authentifier depuis une application tierce (ici Dynamo)
- un 1ᵉʳ exemple pour lister les utilisateurs des Projets ACC
Dans la suite de cet article, nous utiliserons Dynamo3 + IronPython3
et la librairie .Net Newtonsoft Json.
Vous trouverez dans un prochain article un exemple avec CPython3 et la libraire python json
Vous trouverez dans un prochain article un exemple avec CPython3 et la libraire python json
- Introduction
APS, ou Autodesk Platform Services, anciennement connu sous le
nom de Forge, est une suite de services cloud offerte par
Autodesk. Elle permet aux développeurs de créer des
applications personnalisées, d'intégrer des flux de travail et
d'automatiser des processus, grâce à plusieurs APIs bien
documentées.
Nous utiliserons dans cet article les API suivantes
- Authentification API
- Autodesk Construction Cloud Platform (ACC) API
- Configuration initiale
Avant de pouvoir utiliser les APIs, APS, il est nécessaire
d'enregistrer l'application pour obtenir un identifiant et un secret
client. Pour plus d'informations, consultez ce
tutoriel : Création d'une application APS
- Authentification et Scopes
La connexion à APS, depuis Dynamo, se fait (dans cet exemple) via
une authentification en deux étapes (2-Legged Token). Ce processus
assure une sécurité renforcée pour l'accès aux APIs.
Nous devons également définir les 'scopes' suivant :
data:read
/
account:read
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 account:read")
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
- Exemple : lister les utilisateurs par projet
Pour cela, nous utilisons la fonction suivante
https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projectsprojectId-users-GET/
voici le code
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 account:read")
response = client.PostAsync("https://developer.api.autodesk.com/authentication/v2/token", FormUrlEncodedContent(parameters)).Result
result = response.Content.ReadAsStringAsync().Result
jobject = JObject.Parse(result)
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)
return jobjectA
out = []
dict_project_users = {}
my_hub_name = "MY_HUB"
# 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"])
for data in data_array_projects:
projectId = data["id"].ToString()
projectName = data["attributes"]["name"].ToString()
#
dict_project_users[projectName] = []
#
j_project_users = get_request_data_management("https://developer.api.autodesk.com/construction/admin/v1/projects/" , projectId, type_items_request ="/users")
data_array_users = JArray(j_project_users["results"])
for user in data_array_users:
email = user['email'].ToString()
name = user['name'].ToString()
role = ""
for i in user["roles"]:
role += i['name'].ToString() + ", "
dict_project_users[projectName].append([email, name, role])
OUT = dict_project_users
.
- Rajout de Paramètres a la requête (Query String Parameters)
Vous pouvez appliquer des filtres de requête grâce aux paramètres
disponible avec cette fonction.
Voici un exemple ou filtre par email et l'on modifie le
nombre maximum d'utilisateurs retournés.
Ici les filtres se mettent en fin d'URI suivant la syntaxe :
Ici les filtres se mettent en fin d'URI suivant la syntaxe :
?
filtre1&
filtre2
j_project_users = get_request_data_management("https://developer.api.autodesk.com/construction/admin/v1/projects/" ,
projectId, type_items_request ="/users?filter[email]=snee&filterTextMatch=contains&limit=50")
un autre exemple pour obtenir les métas-datas incluant le chemin
j_data_file = get_request_data_management("https://developer.api.autodesk.com/data/v1/projects/" , my_project_id, type_items_request ="/items/{}?includePathInProject=true".format(file_id))
pathInProject = j_data_file["data"]["attributes"]["pathInProject"].ToString()
folder_name = pathInProject.split("/")[-1]
Voici une bonne documentation sur les conventions d'URI
https://www.odata.org/documentation/odata-version-2-0/uri-conventions/
https://www.odata.org/documentation/odata-version-2-0/uri-conventions/
- Plus rapide ?
Vous pouvez également tenter d'utiliser du multi-threading, mais attention
à la limite des quotas imposés par l'API APS
https://aps.autodesk.com/en/docs/data/v2/developers_guide/rate-limiting/forge-rate-limits/
https://aps.autodesk.com/en/docs/data/v2/developers_guide/rate-limiting/dm-rate-limits/
https://aps.autodesk.com/en/docs/data/v2/developers_guide/rate-limiting/dm-rate-limits/
le même code avec des Threads
import sys
import clr
import System
from System.Collections.Generic import List, IList, Dictionary
from System.Threading import Thread, ThreadStart
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 *
import time
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 account:read")
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)
return jobjectA
def get_users_project(data):
dict_users = {}
projectId = data["id"].ToString()
projectName = data["attributes"]["name"].ToString()
#
dict_users[projectName] = []
#
j_project_users = get_request_data_management("https://developer.api.autodesk.com/construction/admin/v1/projects/" , projectId, type_items_request ="/users")
data_array_users = JArray(j_project_users["results"])
for user in data_array_users:
email = user['email'].ToString()
name = user['name'].ToString()
role = ""
for i in user["roles"]:
role += i['name'].ToString() + ", "
dict_users[projectName].append([email, name, role])
return dict_users
class Worker():
__slots__ = 'fn', 'args', 'result'
def __init__(self, fn, args):
self.fn = fn
self.args = args
self.result = None
def __call__(self):
self.result = self.fn(*self.args)
start = time.time()
out = []
dict_project_users = {}
my_hub_name = "MY_HUB"
# 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"])
# set workers
workers, tasks = [], []
for data in data_array_projects:
w = Worker(get_users_project, (data,))
t = Thread(ThreadStart(w))
workers.append(w)
tasks.append(t)
t.Start()
for t in tasks: t.Join()
# merge all dict
out_dict = {}
for x in workers:
out_dict = dict(out_dict, **x.result)
elapsed = time.time() - start
OUT = elapsed, out_dict
Dans un prochain article, nous verrons un exemple un peu plus complexe
(recherche de fichiers au sein d'un projet).
« Il vaut mieux être un optimiste qui se trompe parfois qu'un pessimiste
qui a toujours raison. »
Mark Twain
0 commentaires:
Enregistrer un commentaire