Tag Archives: Dynamo

Dynamo’s Security Vulnerability

Last week, I decided to see how far I could push Python nodes in Dynamo in terms of files external of Revit and I believe I have discovered a vulnerability in which an attacker can use a Python node within a Dynamo graph to gain access to your desktop. There have been some similar discussions on the Dynamo forums earlier this year, however the discussion revolved around the possibility of malicious custom packages. The difference (and frightening part) about this vulnerability is you do not need to download a custom package to your hard drive to be exposed to this hack.

Example

If you would like to see an example of how this works, download this graph and open it in Dynamo. It is a simple graph with a Python Node. You do not need to be knowledgeable in Python to understand this example.

Dynamal (31 downloads)

How it works

If you opened the Dynamo graph, you will notice that it was set to automatically run. This means the graph has already executed all it needs to add the malware to your hard drive. With around 30 lines of code, this graph created a folder on your C-drive disguised as a system folder, downloaded a file from the internet without your permission, and saved this file to your hard drive.

For the sake of this example, I’ve added a dialog window that pops up once the script has been run. An attacker would not have the courtesy to give you this notification as their intention is to save malware to your PC without you knowing.

What’s the harm in downloading a file without permission?

Most harmful files need to be executed in order for an attack to be successful and Windows will most likely prompt you before running any executable. However, are you paying attention when you run software updates?

A prime example of malware disguised as a software updater is the well-documented Placeholder Trojan. This simple script can give an attacker access to every keystroke you press as well as the ability to send screenshots of your PC to an attacker. This Trojan can be easily disguised as a Java updater as described in “Placeholder Trojan: Writing a Malware Software” by Garrett Bourg, Matt Bullock, and Robert Miller (A paper written under the guidance of Prof. Raj Jain).

Potential

Creating folders and downloading files is only one example of the vulnerability that Python exposes. Python essentially exposes your files and folders and has the ability to delete, upload, and execute files without your approval.

Conclusion

Let this serve as warning to all of my fellow Dynamo users out there. Be cautious of opening Dynamo graphs from sources that you do not trust. Malicious code can be hidden deep within complex graphs and custom packages.

Use Dynamo to Transfer Phase Data to Bound Revit Models

This workflow was created as a request from @PhilosophyBIM on Twitter

The issue arises when binding a linked model in Revit. If you’ve ever had the task of binding a linked model that contains crucial Phase data,  you’ve run into the issue where the Phase data is lost regardless of whether the phase exists in the destination model or not. I hope this helps eliminate some tedious work for some Revit users out there!

In a nutshell, this process temporarily stores the phase data (e.g., “Existing” and “New Construction”) in Project Parameters. Once those values are stored, a second graph sets the Revit Phase data based on those parameter values.

Note that this was tested on a simple project with only two phases. Please experiment on a detached model when trying out this workflow.

Download the Dyn’s:

Dynamo - Transfer Revit Phases to Bound Model (71 downloads)

The Workflow

1. In your source model (the model to be bound), create three project parameters.

Use Project Parameters to transfer Revit phase data to bound linked Revit models

These parameters are used to temporarily store the data from Revit’s built-in Phase parameters. The third parameter is an added bonus of storing Element ID’s for simplified quality control.

  1. SourcePhaseCreated
  2. SourcePhaseDemolished
  3. SourceElementId (this is used for QC if so desired)

Use your judgement on which categories to apply the parameters to, but for the sake of simplicity, I would recommend to apply these project parameters to all categories.

2. Create a 3D View that hides all annotations.

You’ll want to make sure that all model elements are visible, because the Dynamo graph collects elements to apply the Parameter values based on what is visible in the active view.

3. Run “Store Element Id and Phase Parameters.dyn”.

Set Parameter values for mapping Revit Phases from linked model after binding

This graph does the work of taking the Phase data from Revit’s built-in parameters and storing their names in the parameters that were created in step one.

While doing some testing, I noticed that Dynamo throws an error because there are certain model elements that cannot be assigned a project parameter. As far as I could tell, this didn’t cause an issue with mapping the Phases to the Parameter values, but please let me know if you find otherwise while using these graphs.

Note that if you would like to double check that the parameters were correctly populated, I recommend to build schedules with the Phases and Parameter values and either run a quick scroll to visually check or run some conditional formatting for larger models.

4. Link the source model into your destination model, bind it, and ungroup the bound elements.

After the model is bound,  note that the Project Parameters created in step one and the values populated from step two have been brought into your destination project.

We aren’t done yet, notice that the Project Parameter values do not match the Phase parameter values.

Parameters used to store Phase data from after linked model bind

5. Finally, run “Set Phase from Phase Parameters.dyn”.

Set Revit Phase after binding linked model from Parameter Value

This graph sets your elements to the proper Phases based on the parameter values populated in step three.

Take some time to look at this graph before you run it, especially if you have more complex phasing in your project. I’ve grouped each set of nodes so that in the instance that you have several Phases, it should be easy to figure out how to duplicate the groups and create a group for as many phases as your project contains.

Download the Dyn’s:

Dynamo - Transfer Revit Phases to Bound Model (71 downloads)

Hope this helps!

Please let me know if this graph does or doesn’t work for you. All feedback is appreciated!

 

Dynamo Graph to push Space data into COBie.Component.Space including elements above the ceiling (MEP)

Here is a graph that I’ve thrown together that pushes the Revit Space number  into the COBie parameter “COBie.Component.Space” for elements that are within the Space, including elements above the ceiling.

Note that in order for this to include the elements in the area above ceilings (i.e., mechanical and electrical equipment), your spaces must use the “Upper Limit” parameter on your spaces to include the elements that are within the ceilings above the Space. This hasn’t been fully tested, so if it doesn’t work for your project please let me know in the comments below.

Push Space number into COBie.Component.Space parameter of elements above ceiling

Workflow

  1. Open the model which contains the elements you wish to populate the COBie parameter (e.g.,  MEP model).
  2. Create spaces and rename/renumber as needed (I recommend the Space Naming Utility).
  3. Launch Dynamo and open the graph linked at the bottom of this post.
  4. In the graph, choose which categories you would like to push the space data into. Modify the List.Join node if you need to add or remove categories from the list.
    COBie space parameter to model categories
  5. Set the graph to Automatic (for an easier workflow)
  6. Use the Select Model Element node to pick a space individually.
    Pick a space in Revit to push to COBie data.
  7. Continue selecting spaces as needed to populate element COBie space data.

Under the Hood

This graph first gets all elements of the chosen categories and then gets the BoundingBox of a space.Get bounding box of space for COBie parameter in Revit

It then filters out the elements whose coordinates are not within the selected Space’s BoundingBox.Get elements within Space for COBie

Finally, the graph pushes the Space’s “Number” parameter value into the “COBie.Component.Space” parameter.

Set Revit Space number to COBie parameter

The unique challenge here was for MEP elements that are above the ceiling. To solve this, I use the Space’s “Upper Limit” parameter to include the ceiling space above the Space.Get Upper Limit parameter to include in bounding box for COBie space data

A new BoundingBox is created using the new MaxPoint from the “Upper Limit”.Include ceiling space in Space height for COBie

Conclusion

I haven’t tested this on complex spaces, so if this doesn’t work for your project, please let me know in the comments below.

This graph could be modified to iterate through all spaces, but I haven’t had a chance to do so. Please, if you end up modifying it to do so, please share the dyn in the comments below so that I can update this post and share with our readers.

Questions, comments, issues?

Space Number to COBie.Component.Space (53 downloads)

BIMxHTML v0.0.8 – More Custom Nodes to Generate Google Charts

It looks like there has been some interest in the BIMxHTML Dynamo package and its encouraged me to develop some custom nodes to simplify the display of Google Charts using pure Dynamo.

The Custom Nodes

Download the sample files below to get a good example of how to use these nodes. Essentially, they output an entire web page and as of today the intent is to use them in the iframes of a dashboard.

Data Set – Quantities of Family Types.dyf

Use this node to build a dictionary of family types of any given category. The output is actually a list of sublists which contain the [key, value] pairs as [family type, quantity]. For example:  [Diffuser24x24, 17].

This node is helpful to use for the input of any of the Google Chart nodes.

Create a data set for use as input to the BIMxHTML nodes.

Generate Web Page – Google Pie Chart.dyf

Creates the complete web page to display a responsive pie chart based on the Google Charts API. The intent for the HTML file is to reference it in an iframe for a dashboard (more on that to come).

Refer to the Google Charts documentation for options input.

Create the HTML for a Google Pie Chart.

Generate Web Page – Google Bar Chart.dyf

This node takes the same exact input as the Pie Chart node and outputs a bar graph.

Refer to the Google Charts documentation for options input.

Create the HTML for a Google Bar Chart.

Sample Files

Refer to the sample Dynamo graphs below to get a better idea of how to use these nodes. Dashboard-Mech.html is currently the best example because it displays a pie chart, a bar chart, and a table – all generated directly from Dynamo.

BIMxHTML-Examples-v0-2.zip (70 downloads)
A dashboard generated using Revit, Dynamo, Bootstrap, and Google Charts.
A dashboard generated using Revit, Dynamo, Bootstrap, and Google Charts.

BIMxHTML – A Dynamo Package to Generate Web Pages

All of the excitement revolving around generating dashboards using Power BI made me wonder: Can we leverage Dynamo to create web pages that display data directly from a Revit model? The goal would be to create a powerful, free alternative to generating web-based content using simple HTML code.

Needless to say, the gears have been turning and I have been experimenting. With that said, I have published my first Dynamo package, BIMxHTML, which will eventually have several nodes to display content on a web page using very basic HTML. I have been playing with Twitter Bootstrap and Google Charts so far.

Update: New nodes have been published to v0.0.8 which streamline the creation of Google Charts. Read up on the nodes here:
http://bimextension.com/bimxhtml-v0-0-8-more-custom-nodes-to-generate-google-charts/

For now a single node is included in the BIMxHTML package: Generate Web Page.

Using Dynamo node to create a static HTML web page.

The inputs for Generate Web Page contain several default values for configuring the <head> of the web page. I have also included inputs to allow users to link to external CSS stylesheets and JavaScript files or embedded code for custom <style> or <script> tags. All without managing the template’s HTML directly.

I have a sample model and graph for you to see the node in action available for download below.

Use Dynamo to generate a static HTML web page.
Sample Dynamo graph using BIMxHTML nodes to create an HTML web page.

Sample Files Explained

There are a few sample graphs included in the download below. Please keep in mind that these are extremely early examples of the possibilities of using Dynamo to extract Revit data and output HTML for display in any modern browser. Currently, I have been experimenting with a combination of Twitter Bootstrap and Google Charts, but if you have any suggestions on other frameworks or analytics tools, please make a suggestion in the comments below.

Table Sample.dyn (TableTest.html)

Creates a list with parameter values as sublists.

  1. Using Python, the HTML code for a table is generated using each list item as a table row and each sublist item as a column value. Note: a custom node will be added to this package to handle this in the near future.
  2. Finally, the Generate Web Page node from the BIMxHTML package creates the entire web page’s code and then writes the code to an external HTML file.

Google Charts – Pie Chart.dyn (Air Terminals.html / Ducts.html)

Creates an HTML page containing a Google Charts pie chart displaying the quantity of family types per category.

Dashboard.html

A sample Bootstrap layout which uses iframes to display the pie charts generated from Google Charts – Pie Chart.dyn.

Use Dynamo and Revit to create a free alternative to Power BI
A dashboard generated using Dynamo, Revit, Twitter Bootstrap, and Google Charts.

Feedback?

Would these tools help you with your workflows? Do you have any suggestions on how I can improve on these? Would you like to help contribute? Please leave your questions and comments below.

BIMxHTML-Sample-Files-1.zip (131 downloads)

Hello Dynamo World!

In learning every new programming language, it is customary to start with a “Hello world!” application. Although visual, Dynamo is a scripting tool as well, so I thought this would be a great first step for folks who are new to Dynamo.

In this post, we demonstrate how to display “Hello world!”  in the Revit application in two ways:

  1. Displaying a TaskDialog in Revit using a combination of Dynamo and Python.
  2. Adding a TextNote to a view using only out-of-the-box (OOTB) nodes.

Hello World Using Dynamo and Python

Hello world Dynamo graph

The image above shows the completed graph (download below). Most of the work is done within the Python script which uses two inputs as variables.

Insert a Python Script node.

Once the node is placed in your graph, you will need to click the “+” button to add an additional input.

Python script node in Dynamo to show a task dialog in Revit.

After adding the second input, you should see IN[1] as shown below.

Python script in Dynamo to show a task dialog in Revit.

Add strings to your input.

For this example, I’ve shown two different nodes that you can use to output strings in Dynamo. The String node outputs a string from the value that you insert into the node (Hello). The Code Block node must include double quotes and a semicolon to output a string (“Hello world!”;).

In computer programming, a string data type is a set of characters. This can be in the form of a sentence or a file path, and can contain special characters and/or spaces. Strings are typically enclosed using double quotes.

Connect the nodes to the inputs as shown below.

Hello world Dynamo graph

Insert code to the Python Script node.

To open the code editor in Dynamo, double-click on the blank area of the node as highlighted below.

Edit a python script in Dynamo

Insert the code below to the code editor. Note that we are including the Autodesk.Revit.UI namespace in order to use the TaskDialog.Show() method from the Revit API.

I highly recommend that you type this code in rather than copy/pasting. It will help you start to understand Python’s syntax.

import clr
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import TaskDialog

windowTitle = IN[0]
windowMessage = IN[1]

messageDialog = TaskDialog
OUT = messageDialog.Show(windowTitle, windowMessage)

If your Dyn is set to run automatically (it is by default)  you should immediately see the dialog box pop up in Revit. If set to manual, click the Run button in the bottom left of Dynamo to run the script.

Here is a link to the Dynamo graph used in this example:
HelloWorld.dyn (81 downloads)

Hello World with OOTB Nodes

Dynamo BIM - Hello World in Revit

The image above is the completed graph (download below) and will create a TextNote in the Revit view of your choice.

1) TextNote.ByLocation
This node does all of the work. It will place a text element in the view that you choose. The node has several inputs, but for this example we will only use the first four inputs.

2) Views
A node that provides a drop down menu of all of the views in your project. Choose a floor plan view in your active model as you follow this example.

3) Point.ByCoordinates
This node outputs a Point based the x, y, z inputs. For this example, I’ve shown three different nodes that you can use to generate number values: 4) Number , 5) Code Block, and 6)Number Slider

7) String
The value in the String node goes into the “text” input for the content of the text note element in the Revit view.

8) String
The value in this String node goes into the “alignment input”

Here is a link to the Dynamo graph used in this example:
Hello World - Text (98 downloads)

Questions? Post your comments below!

Seattle Dynamo User Group

Rather than hosting a Dynamo training session in the greater Seattle area, we decided to organize and sponsor the Seattle Dynamo User Group Meetup! The meetup group was only formed on February 1, 2017 and we already have 17 members.

We will schedule the first meetup as soon as we have speaker and a venue in place. We are currently searching for both, so please let us know if you can help us find either of the two.

We are extremely excited to lead this community! Here’s to sharing, learning, and networking with other Dynamo users in Seattle.

Seattle Dynamo User Group

Seattle, WA
20 Members

Are you interested in using Dynamo to streamline workflows, build complex geometry, or harness BIM data? Join us to learn and share experiences about this exciting new visual …

Check out this Meetup Group →

 

Use Dynamo to delete all views in Revit

I have been working on a Dynamo Workflow that will purge out all views and sheets from a Revit model. Yes, there are several add-ins that currently accomplish this task, however I eventually want to create a “Super Purge” Workflow that will purge a model of all views, sheets, and elements for me. More on that to come.

Requirements:

  • Clockwork
  • Springs
  • Dynamo

The Workflow

Use Dynamo to delete all views in Revit.

The SetDifference node is grabbing all views in the current document from the Document.Views node and removes the  user-specified view to keep in the model from the Views node. Note that Revit maintains the requirement to have at least one view within a project.

Then, the Springs.Doc.DeleteElements node deletes all views (except for the one chosen in step one).

Download

Dynamo - Delete all Views (398 downloads)

Special Thanks

A special thanks goes out to the good folks at DynamoBIM.com for helping me out with this solution.

Coming Soon: Dynamo training in Seattle, San Francisco



We are extremely excited to announce that we will be hosting our first Dynamo training session in January 2017. The class is intended for Revit users who would like to leverage Dynamo to eliminate repetitive tasks and build complex geometry in Revit.

The class will be held in either Seattle, Bellevue, or San Francisco – location is TBD. Subscribe to our mailing list above if you would like to be notified of any updates regarding the upcoming Dynamo training session in Seattle, Washington.

Copy a Legend to Multiple Sheets in Revit

The good folks over at Boost Your BIM have posted a macro for copying a legend to multiple sheets. It works really well, but I wonder if anyone would like to take on the challenge of doing something similar in Dynamo.

public void legendOnSheets()
{
    Document doc = this.ActiveUIDocument.Document;
    
    // create list of element ids for the sheets that will get the legends
    List<ElementId> sheetIds = new List<ElementId>();
        
    // use SheetNumber to find the desired sheets
    // add each sheet to the list of sheet ids
    sheetIds.Add(new FilteredElementCollector(doc)
        .OfClass(typeof(ViewSheet))
        .Cast<ViewSheet>()
        .FirstOrDefault(q => q.SheetNumber == "A101").Id);
    sheetIds.Add(new FilteredElementCollector(doc)
        .OfClass(typeof(ViewSheet))
        .Cast<ViewSheet>()
        .FirstOrDefault(q => q.SheetNumber == "A102").Id);                
    sheetIds.Add(new FilteredElementCollector(doc)
        .OfClass(typeof(ViewSheet))
        .Cast<ViewSheet>()
        .FirstOrDefault(q => q.SheetNumber == "A103").Id);    
    
    // find the legend to put on the sheets
    // use ViewType.Legend and the view name to find the legend view
    Element legend = new FilteredElementCollector(doc)
        .OfClass(typeof(View))
        .Cast<View>()
        .FirstOrDefault(q => q.ViewType == ViewType.Legend && q.Name == "Legend 1");
    
    // create a transaction so that the document can be modified
    using (Transaction t = new Transaction(doc, "Legends on Sheets"))
    {
        // start the transaction
        t.Start();
        
        // loop through the list of sheet ids
        foreach (ElementId sheetid in sheetIds)
        {
            // create a new viewport for the legend on each sheet
            // place the legend view at the 0,0,0 location on each sheet
            // user will need to move the legend to the desired location
            Viewport.Create(doc, sheetid, legend.Id, new XYZ(0,0,0));
        }
        
        // commit the changes
        t.Commit();
    }
}