ChuongHo
ChuongHo

Reputation: 89

How to update parameter for Revit Model BIM360 Cloud CompositeDesign With Design Automation?

I have issue need update for Architect model (.rvt) used Composite Design linking with many model on BIM360. But when I'm try with Design Automation, I failed at the latest step.Let's me show step by step I'm tried to achieve :

  1. Unzip Composite Design Automation (Worked)
  2. Set new value for Element by Parameter Name (Worked)
  3. Update new version for Composite Design Model(.rvt) - I don't know how to update version with Zip file ?.

Can give me a example to get step 3, I just sucess with single file (.rvt) only, this is my code :

private static async Task<string> CreateFileStorage(string projectId, string folderUrn, string filename,
        string accessToken)
    {
        ProjectsApi projectsApi = new ProjectsApi();
        projectsApi.Configuration.AccessToken = accessToken;

        var storageRelData =
            new StorageRelationshipsTargetData(StorageRelationshipsTargetData.TypeEnum.Folders, folderUrn);
        var storageTarget = new CreateStorageDataRelationshipsTarget(storageRelData);
        var storageRel = new CreateStorageDataRelationships(storageTarget);
        var attributes =
            new BaseAttributesExtensionObject(string.Empty, string.Empty, new JsonApiLink(string.Empty), null);
        var storageAtt = new CreateStorageDataAttributes(filename, attributes);
        var storageData = new CreateStorageData(CreateStorageData.TypeEnum.Objects, storageAtt, storageRel);
        var storage = new CreateStorage(new JsonApiVersionJsonapi(JsonApiVersionJsonapi.VersionEnum._0), storageData);

        try
        {
            var res = await projectsApi.PostStorageAsync(projectId, storage).ConfigureAwait(false);
            string id = res.data.id;
            return id;
        }
        catch (ApiException ex)
        {
            throw new Exception(ex.Message);
        }
    }

    private static async Task<ObjectDetails> UploadFileAsync(string objectStorageId, MemoryStream fileMemoryStream,
        string accessToken)
    {
        var objectInfo = ExtractObjectInfo(objectStorageId);
        // Get object upload url via OSS Direct-S3 API
        var objectsApi = new ObjectsApi();
        objectsApi.Configuration.AccessToken = accessToken;

        var payload = new List<UploadItemDesc>
        {
            new UploadItemDesc(objectInfo.ObjectKey, fileMemoryStream)
        };

        var results = await objectsApi.uploadResources(
            objectInfo.BucketKey,
            payload
        ).ConfigureAwait(false);

        if (results[0].Error)
        {
            throw new Exception(results[0].completed.ToString());
        }

        var json = results[0].completed.ToJson();
        return json.ToObject<ObjectDetails>();
    }

    private static ObjectInfo ExtractObjectInfo(string objectId)
    {
        var result = System.Text.RegularExpressions.Regex.Match(objectId, ".*:.*:(.*)/(.*)");
        var bucketKey = result.Groups[1].Value;
        ;
        var objectKey = result.Groups[2].Value;

        return new ObjectInfo
        {
            BucketKey = bucketKey,
            ObjectKey = objectKey
        };
    }

    private static async Task<FileInfoInDocs> CreateFileItemOrAppendVersionAsync(string projectId, string folderUrn,
        string objectId, string filename, string accessToken)
    {
        ItemsApi itemsApi = new ItemsApi();
        itemsApi.Configuration.AccessToken = accessToken;
        string itemId = "";
        string versionId = "";
        // check if item exists
        var items = await GetFolderItems(projectId, folderUrn, accessToken).ConfigureAwait(false);
        var item = items.Cast<KeyValuePair<string, dynamic>>().FirstOrDefault(item =>
            item.Value.attributes.displayName.Equals(filename, StringComparison.OrdinalIgnoreCase));
        FileInfoInDocs? fileInfo;
        if (item.Value != null)
        {
            //Get ItemId of our file
            itemId = item.Value.id;

            //Lets create a new version
            versionId = await UpdateVersionAsync(projectId, itemId, objectId, filename, accessToken).ConfigureAwait(false);

            fileInfo = new FileInfoInDocs
            {
                ProjectId = projectId,
                FolderUrn = folderUrn,
                ItemId = itemId,
                VersionId = versionId
            };

            return fileInfo;
        }
        var itemBody = new CreateItem
        (
            new JsonApiVersionJsonapi
            (
                JsonApiVersionJsonapi.VersionEnum._0
            ),
            new CreateItemData
            (
                CreateItemData.TypeEnum.Items,
                new CreateItemDataAttributes
                (
                    DisplayName: filename,
                    new BaseAttributesExtensionObject
                    (
                        Type: "items:autodesk.bim360:File",
                        Version: "1.0"
                    )
                ),
                new CreateItemDataRelationships
                (
                    new CreateItemDataRelationshipsTip
                    (
                        new CreateItemDataRelationshipsTipData
                        (
                            CreateItemDataRelationshipsTipData.TypeEnum.Versions,
                            CreateItemDataRelationshipsTipData.IdEnum._1
                        )
                    ),
                    new CreateStorageDataRelationshipsTarget
                    (
                        new StorageRelationshipsTargetData
                        (
                            StorageRelationshipsTargetData.TypeEnum.Folders,
                            Id: folderUrn
                        )
                    )
                )
            ),
            new List<CreateItemIncluded>
            {
                new CreateItemIncluded
                (
                    CreateItemIncluded.TypeEnum.Versions,
                    CreateItemIncluded.IdEnum._1,
                    new CreateStorageDataAttributes
                    (
                        filename,
                        new BaseAttributesExtensionObject
                        (
                            Type: "versions:autodesk.bim360:File",
                            Version: "1.0"
                        )
                    ),
                    new CreateItemRelationships(
                        new CreateItemRelationshipsStorage
                        (
                            new CreateItemRelationshipsStorageData
                            (
                                CreateItemRelationshipsStorageData.TypeEnum.Objects,
                                objectId
                            )
                        )
                    )
                )
            }
        );


        try
        {
            DynamicJsonResponse postItemJsonResponse = await itemsApi.PostItemAsync(projectId, itemBody).ConfigureAwait(false);
            var uploadItem = postItemJsonResponse.ToObject<ItemCreated>();
            Console.WriteLine("Attributes of uploaded BIM 360 file");
            Console.WriteLine($"\n\t{uploadItem.Data.Attributes.ToJson()}");
            itemId = uploadItem.Data.Id;
            versionId = uploadItem.Data.Relationships.Tip.Data.Id;
        }
        catch (ApiException ex)
        {
            //we met a conflict
            dynamic? errorContent = JsonConvert.DeserializeObject<JObject>(ex.ErrorContent);
            if (errorContent.Errors?[0].Status == "409") //Conflict
            {
                try
                {
                    //Get ItemId of our file
                    itemId = await GetItemIdAsync(projectId, folderUrn, filename, accessToken).ConfigureAwait(false);

                    //Lets create a new version
                    versionId = await UpdateVersionAsync(projectId, itemId, objectId, filename, accessToken).ConfigureAwait(false);
                }
                catch (Exception ex2)
                {
                    System.Diagnostics.Trace.WriteLine("Failed to append new file version", ex2.Message);
                }
            }
        }

        if (string.IsNullOrWhiteSpace(itemId) || string.IsNullOrWhiteSpace(versionId))
        {
            throw new InvalidOperationException("Failed to Create/Append file version");
        }

        fileInfo = new FileInfoInDocs
        {
            ProjectId = projectId,
            FolderUrn = folderUrn,
            ItemId = itemId,
            VersionId = versionId
        };

        return fileInfo;
    }

    private static async Task<string> UpdateVersionAsync(string projectId, string itemId, string objectId,
        string filename, string accessToken)
    {
        var versionsApi = new VersionsApi();
        versionsApi.Configuration.AccessToken = accessToken;

        var relationships = new CreateVersionDataRelationships
        (
            new CreateVersionDataRelationshipsItem
            (
                new CreateVersionDataRelationshipsItemData
                (
                    CreateVersionDataRelationshipsItemData.TypeEnum.Items,
                    itemId
                )
            ),
            new CreateItemRelationshipsStorage
            (
                new CreateItemRelationshipsStorageData
                (
                    CreateItemRelationshipsStorageData.TypeEnum.Objects,
                    objectId
                )
            )
        );
        var createVersion = new CreateVersion
        (
            new JsonApiVersionJsonapi
            (
                JsonApiVersionJsonapi.VersionEnum._0
            ),
            new CreateVersionData
            (
                CreateVersionData.TypeEnum.Versions,
                new CreateStorageDataAttributes
                (
                    filename,
                    new BaseAttributesExtensionObject
                    (
                        "versions:autodesk.bim360:File",
                        "1.0",
                        new JsonApiLink(string.Empty),
                        null
                    )
                ),
                relationships
            )
        );

        dynamic versionResponse = await versionsApi.PostVersionAsync(projectId, createVersion).ConfigureAwait(false);
        var versionId = versionResponse.data.id;
        return versionId;
    }

    private static async Task<string> GetItemIdAsync(string projectId, string folderUrn, string filename,
        string accessToken)
    {
        FoldersApi foldersApi = new FoldersApi();
        foldersApi.Configuration.AccessToken = accessToken;
        DynamicDictionaryItems itemList = await GetFolderItems(projectId, folderUrn, accessToken).ConfigureAwait(false);
        var item = itemList.Cast<KeyValuePair<string, dynamic>>().FirstOrDefault(item =>
            item.Value.attributes.displayName.Equals(filename, StringComparison.OrdinalIgnoreCase));
        return item.Value?.Id;
    }

    private static async Task<DynamicDictionaryItems> GetFolderItems(string projectId, string folderId,
        string accessToken)
    {
        var foldersApi = new FoldersApi();
        foldersApi.Configuration.AccessToken = accessToken;
        dynamic folderContents = await foldersApi.GetFolderContentsAsync(projectId,
            folderId,
            filterType: new List<string>() {"items"},
            filterExtensionType: new List<string>() {"items:autodesk.bim360:File"}
        ).ConfigureAwait(false);

        var folderData = new DynamicDictionaryItems(folderContents.data);

        return folderData;
    }
}

public class ObjectInfo
{
    public string BucketKey { get; set; }
    public string ObjectKey { get; set; }
}

public class FileInfoInDocs
{
    public string ProjectId { get; set; }
    public string FolderUrn { get; set; }
    public string ItemId { get; set; }
    public string VersionId { get; set; }
}

Any help is appreciate !!

Upvotes: 0

Views: 115

Answers (1)

Xiaodong Liang
Xiaodong Liang

Reputation: 2196

Sorry for letting you wait.

If you meant by the main model of cloud sharing of Revit, you could use this API to publish the model like Revit desktop does https://aps.autodesk.com/en/docs/data/v2/reference/http/PublishModel/

This assumes your Design Automation plugin has saved the updated main model to cloud sharing (same to the step Collaborate>>Sync in Revit). https://aps.autodesk.com/blog/design-automation-api-supports-revit-cloud-model

While you mentioned zip file, could you clarify if this refers to the scenario when some linked updated models have not been published, so when downloading main model from BIM360, it will be a zip (i.e. File Item attribute isCompositeDesign=true)? This blog tells details of such scenario. https://aps.autodesk.com/blog/make-composite-revit-design-work-design-automation-api-revit

If yes, your workflow input this zip for design automation, the zip will be unpackaged to main model and latest linked models. and your plugin updates parameter of the main model, right? In any case, as long as your plugin of Design Automation updates and saves to cloud, you can just call that API PublishModel to perform the action. Cloud sharing model item is not like common model item which you create version by Post Version.

If I misunderstand your use case, please feel free to discuss further.

Upvotes: 0

Related Questions