I have developed a working BIM360 to on-premises backup mechanism. There were a few different ways to go…

 

I initially considered:

  • Hacking Windows Explorer to touch the files in the BIM 360 node and try and trigger the BIM360 Docs download and copy to local PC or network location
  • Developing a Forge app that essentially pulls the desired models out of the BIM 360 cloud to desired location?

In the end, I decided to use the Revit API (Dynamo and Python), along with VirtualBuiltApp, to essentially reverse engineer a folder structure from the local CollaborationCache folder. These ideas are hinted at here.

 

In simple terms, the BIM 360 Docs on-premises backup workflow is:

  1. Create a super federated BIM 360 model (with all other BIM 360 models linked into it)
  2. A Dynamo script reloads all links in order to cache them locally
  3. The same script interrogates, then determines the target file name and folder from VirtualBuiltApp
  4. Dynamo then copies the files into their ‘backup’ location on the local network

 

Some more detail is presented below:

 

A) Cache Cleaner CMD Script (may not really be necessary, as the ‘reload’ should overwrite superseded cache anyway):

Kill Revit if Open… be careful of below steps, particularly if Revit has crashed recently. You might need these local copies 🙂

cd "%LOCALAPPDATA%\Autodesk\Revit\Autodesk Revit 2018"
cd CollaborationCache
rmdir oldCache
mkdir oldCache
for /d %i in (*) do move "%~i" oldCache

 

B) Manual steps to setup Revit model environment to run the script:

  1. Open Revit
  2. Open Federated BIM 360 file (worksets closed)
  3. Unload all links
  4. Open all Worksets

 

C) Dynamo Script:
Run Dynamo (Python) script that reloads and unloads all links (this collects .rvt into cache). Key Python commands to use are: RevitLinkType.Load() and RevitLinkType.Unload(None).

Potential Problems:

  • Coordination Monitor alert, no longer exists
  • Instance of link needs Coordination Review
  • “Some numerical data within the imported file was out of range. This numerical data has been truncated.”
  • “Geometry in the file … has extents greater than 20 miles (33km).”

Local cached Models appear into

%LOCALAPPDATA%\Autodesk\Revit\Autodesk Revit 2018\mainCacheFolder\hostModelIdFolder\LinkedModels\*.rvt

 

D) Dynamo Script continues to:
Rename and copy to desired target location. How do we determine this?

Using proprietary VirtualBuiltApp schema:

  1. Use known directory data along with known JSON data for the BIM 360 files (harvested previously by our proprietary systems)
  2. Build list of target paths
  3. Run copy from Dynamo to copy to target network directory

Part of the script:

 

Note: you can actually browse some BIM 360 Docs data in a .sqlite3 file located in path shown below. You can use DB Browser for SQLite as a viewer.

I came across this link to a Dynamo seminar by Sol Amour delivered in Wellington about a month ago. I have had a bit of contact with Sol over the years and he is a Dynamo pro. Cool to see that Dynamo Nodes got mentioned too.

Check out the seminar here.

As you can tell by his headshot, he means business 🙂

There is some more information about the event at this link.

The official build of Dynamo 2.0 is here. There are some big changes, so here are my key takeaways:

  • File format has changed
  • Automatic backups will be saved of 1.x files after upgrade
  • Dynamo 2.0 will run side by side with a previous version
  • New direction is “desktop to web workflows” (bye XML, hello JSON)
  • Custom packages are now separated from built in nodes in the node library
  • ‘Run’ button on the python editor
  • New focus on dictionaries (bye GetItemAtIndex, hello new Dictionary nodes)

Download at this link

Read the official post at this link

The Revit API is actually something pretty special. People will go on and on about how Revit needs this feature or that feature, but the fact is that you can build almost any feature you like with the API. Recently, I have been running quite a few batch operations from the scope of a federated Revit model: so I will have one RVT file, with hundreds of Revit links, and I will process them from that main federated model.

On one recent project, we had to deliver to a Client a linked dataset, with Revit link file paths resolving correctly. As you know, people work in many different IT environments, and the pathing of Revit links may vary widely.

I set up an ‘approved’ list of Revit file paths, that looked something like this:

I knew that in Dynamo with Python I could get a lot of information about linked files using the ExternalFileReference class. What I discovered during this process is that there is a TransmissionData API class that let’s you do some pretty interesting things…

You see, I was thinking I would have to set up a batch method to open this files, change the file paths, and close them. But the TransmissionData class is basically what is implemented in eTransmit for Revit – it allows you to ‘lightly touch’ the Revit file and simply change the Revit link paths, and also set a switch saying ‘this file has been transmitted’. This puts the file in an appropriate state for re-opening in the new path environment. Pretty cool huh?

Once I figured out how to implement those TransmissionData actions in Python, I just had to build a node that, running from the federated model:

  • examines each link for the links inside of it
  • replaces erroneous paths with the correct file path
  • sets the new paths to the file

I did this in the hacky way of a “counter with List.Map” in Dynamo. In the future I’ll probably fix it up to be a ‘proper’ Python script but this works for now. In about an hour it fixed the linked file paths of 600 Revit links, all with the click of a single button 🙂

You can download the main definition here:

External References FINAL

You can get the supporting nodes from GitHub here:

https://github.com/LukeyJohnson/BakeryForDynamo/tree/master/nodes

As usual, please use with care. And it is probably worth backing up your files before running something like this.

It is kinda more Python than Dynamo but hey, you get the picture 🙂

In fact, here is the Python code:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

from System import Guid

import System

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

import os.path

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

tempvalue = IN[0]
approvedFilenames = IN[1]
approvedFilepaths = IN[2]
targetfilepath = IN[5]

def stripquotes(string):
	string = string[1:-1]
	return string

transData = TransmissionData.ReadTransmissionData(tempvalue)
erefids = transData.GetAllExternalFileReferenceIds()
refdata = []
for x in erefids:
	refdata.append(transData.GetDesiredReferenceData(x))

currentpaths, currenterefType, currenterefPath, pstr = [], [], [], []

for e in refdata:
	currentpaths.append(ExternalFileReference.GetAbsolutePath(e))
	currenterefType.append(e.ExternalFileReferenceType)
	currenterefPath.append(e.PathType)
for s in currentpaths:
	pstr.append(ModelPathUtils.ConvertModelPathToUserVisiblePath(s))
	
filenames = []
for p in pstr:
	templist = os.path.split(p)
	filenames.append(templist[1])
	
newpath = []
indices = []
failpath = []
origcounter = 0
matchrefs = []
newpathtypes, newbools = [], []
pathtypevar = IN[3]
for f in filenames:
	tempindex = approvedFilenames.index(f) if f in approvedFilenames else -1
	indices.append(tempindex)
	if tempindex == -1:
		failpath.append(origcounter)
		pass
	else:
		newpath.append(ModelPathUtils.ConvertUserVisiblePathToModelPath(stripquotes(approvedFilepaths[tempindex])))
		matchrefs.append(erefids[origcounter])
		newpathtypes.append(pathtypevar)
		newbools.append(True)
	origcounter = origcounter + 1

currentfilepathstring=ModelPathUtils.ConvertModelPathToUserVisiblePath(targetfilepath)
elementcount = len(erefids)
hostfile = currentfilepathstring * elementcount
currentdata = []
#currentdata.append(transData)
currentdata.append(hostfile)
currentdata.append(erefids)
currentdata.append(refdata)
currentdata.append(currentpaths)
currentdata.append(currenterefType)
currentdata.append(currenterefPath)
currentdata.append(pstr)
currentdata.append(filenames)

newdata = []
newdata.append(indices)
newdata.append(newpath)
newdata.append(matchrefs)
newdata.append(newpathtypes)
newdata.append(newbools)

setlength = len(newpath)
setcounter = range(setlength)
successreport = []
setdata = IN[4]
if setdata:
	for s in setcounter:
		try:
			transData.SetDesiredReferenceData(matchrefs[s], newpath[s], newpathtypes[s], newbools[s])
			successreport.append("Success setting data")
		except:
			successreport.append("Failure setting data")
else:
	successreport.append("You need to set the switch to True")

if setdata:
	try:
		transData.IsTransmitted = True
		transData.WriteTransmissionData(targetfilepath, transData)
		successreport.append("Success WRITING data")
	except:
		successreport.append("Failure WRITING data")
		
#Assign your output to the OUT variable.
OUT = successreport, currentdata, newdata
 

If you want to read more about the API methods used:

TransmissionData

ModelPathUtils

ExternalFileReference

So, you are modelling this awesome conceptual design with Dynamo and Revit, and you realise “hey, what we need is access to the Star Wars API in here…”

Yes? Well, thanks to Jostein Berger Olsen, you can just open up your Package Manager and install SWAPI package:

swapi.png

And do stuff like this:
starwars.png

Nice work @jos_ols 🙂

Check out the original post:
Revit Dynamite and Ammo: Star Wars API and Dynamo

I had a good time at RTC back in 2016, it was awesome to catch up with the usual BIM crew and see what they are all up to. Hopefully I’ll get a chance to post in more detail about a few things I learned this time around… but for now, here are my 2016 presentations for you to check out.

My keynote presentation slides (why BIM is broken and how to fix it…)

My Dynamo presentation slides:

And the Revizto session that I ran with Michael Clothier:

Presentation and handout resources (including Dynamo dataset) are available in the folder here:
https://drive.google.com/folderview?id=0B1dGdRkpk2beZ3VRRUpiYVctakU&usp=sharing

Quite a momentous day!

You can download it at:
http://dyn-builds-data.s3-us-west-2.amazonaws.com/DynamoInstall1.0.0.exe

(or you can wait for the auto update 🙂

dynamoVersion1.png

 

location.png

Readme:
### 1.0.0 ###

– API Stabilization:  1.0.0 is a commitment to stable code that allows for smoother and more reliable movements from one version to another.  To more clearly express this, we have been moving to “semantic versioning” to illustrate the nature of changes in each release. We will be using the fairly standard version naming with an x.y.z system, where x incrementing represents breaks to the API (requiring developer refactors), y indicates changes that are still backwards compatible, and z are smaller bug fixes.  Package creators and maintainers are encouraged to assess changes to the previous code, which can be found here

https://github.com/DynamoDS/Dynamo/wiki/Dynamo-Node-Changes

https://github.com/DynamoDS/Dynamo/wiki/API-Changes
– Graphics performance enhancements:  see this post for details
https://github.com/DynamoDS/Dynamo/pull/6356
– Documentation: Along with new sections of the DynamoPrimer (http://DynamoPrimer.com), we have started an online documentation of the Dynamo API with a searchable index of public API calls for core functionality. This will be expanded to include regular nodes and Revit functionality.  http://dynamods.github.io/DynamoAPI/
– Licensing:  Dynamo Studio is now using a new version of the Autodesk installer that allows for easier access to network and token flex licensing tools
– Install:  we have created a separate installation for “core” Dynamo functionality, those tools used by all implementations of Dynamo, and Revit, and Studio installations.  This allows for the sharing of a common core of Dynamo code and packages.
– List Management:  Changes to “replication” or automated matching of different data streams in nodes and Code Block nodes eliminates the need for List.Map and List.Combine in many situations
– Send to Web: formerly known as Share Workspace, we have improved the ability to view and interact with Dynamo online with Customizers
– File Export:  Users can now author DWG files in the Translation section of Dynamo Studio.
– Direct Shape:  Dynamo in Revit 2017 can now take advantage of faster and more sophisticated direct shape creation.  In most cases, solid and surface geometry can be sent directly into the Revit environment as smooth (rather than tesselated) surfaces and solids, categorized to whatever is needed.  In the cases where a smooth element cannot be created, a tesselated (mesh) object is created, as was the case previously.

Bug Fixes
– An extensive list can be found here: http://dynamobim.org/incoming-bug-fixes-for-dynamo-1-0-0

Known Issues
– Listed here: https://github.com/DynamoDS/Dynamo/wiki/Known-Issues

1180.png

Also:
Dynamo Builds

It can be pretty hard to track what is visible in a big federated model, and even harder to figure out when something has been changed or updated. Until now…

Check this little node out:

This gets five pieces of information and writes each of them to a View instance parameter. Currently, it works in the context of the currently active view in Revit. The information acquired is as follows:

  • current date / time
  • worksets currently opened
  • RVT links that are visible in the view
  • the file sizes of those links
  • the date modified for those links

The ‘list items’ are converted to a string with line breaks. Then when it is referenced in a Label in a View Title family (on the far right of image above), it basically shows up as a list.

Future applications of this can easily include reading the link status from the view parameter (by converting the string back to a list), comparing it to current link status, and then immediately showing what models have been updated and need to be reloaded…