Python data to Revit [Generic Annotations]

Hi lovely Speckle people! I’m a very enthusiastic Speckle user, but writing scripts etc is new for me - so I’m coming here to see if what I’m trying is even possible ^^. I’m currently trying to setup a workflow that uses .json data (generated via a tool) to replace values inside of a Revit Family. See below for more information:

  • Speckle Status: All good

  • Objective: Would like to send (.json) data from Python to Speckle and receive this inside Revit to update parameters inside of a Generic Annotations family. We “need” a place to store this data too, that’s why I was thinking of using Speckle!

  • Issue: With my good friend Co-Pilot, I’ve created a Python script where I push the .json data to my desired Speckle stream. Receiving this data into Grasshopper and deconstructing the Speckle objects, makes it look like its properly converting this data to (in my opinion) something usable.
    Now when I try to receive this data from the stream into my Revit model, and try to update the Generic Annotations family, nothing happens sadly enough.

  • Speckle link: Test Data Python > Revit | Speckle

Json data:
{
“family_name”: “GA_Rebar_legend_Eurocode_2_ZF”,
“type_name”: “NEN_EN”,
“parameters”: [
{
“name”: “8LOA”,
“value”: 553,
“units”: “unitless”
},
{
“name”: “8LOB”,
“value”: 790,
“units”: “unitless”
}
]
}

Code “we” wrote:

import json
from specklepy.api.client import SpeckleClient
from specklepy.api.credentials import get_default_account
from specklepy.objects import Base
from specklepy.transports.server import ServerTransport
from specklepy.api import operations

# Step 1: Connect to Speckle
client = SpeckleClient(host="https://rhdhv.speckle.xyz")
account = get_default_account()

# Print account details for verification
print(f"Authenticated account: {account}")

client.authenticate_with_account(account)

# Step 2: Read the .json file
with open('*Filepath\\Downloads\\output.json*', 'r') as file:
    data = json.load(file)

# Step 3: Create a new Speckle object
speckle_object = Base()

# Add the parameters to the Speckle object
parameters = []
for param in data["parameters"]:
    param_obj = Base()
    param_obj["name"] = param["name"]
    param_obj["value"] = param["value"]
    param_obj["units"] = param["units"]
    parameters.append(param_obj)

speckle_object['parameters'] = parameters

# Add family and type information
speckle_object['family_name'] = data["family_name"]
speckle_object['type_name'] = data["type_name"]

# Verify the structure of the Speckle object
print(f"Speckle object data: {speckle_object}")

# Step 4: Send the object to Speckle and get the objectId
transport = ServerTransport(client=client, stream_id="22a48a24cc")
object_id = operations.send(base=speckle_object, transports=[transport])

# Step 5: Create a new commit in the stream
commit_id = client.commit.create(
    stream_id="22a48a24cc",
    object_id=object_id,
    message="New version from script"
)

print(f"Object sent to stream 22a48a24cc, commit {commit_id}")

Heres an image of what the family looks like; I would like to update this table with the parameters found to the right. Am currently testing with the 8LOA and 8LOB values first - would like to update all parameters eventually.

How the data looks like in Grasshopper:

Would love to hear the possibilities and if there is a possible solution to this! Thanks in advance, if any more information is needed, I can try and share it.

Thanks in advance!

Hey @Zacheyre_RHDHV!

Thanks for the super clear post. Sounds like an interesting “problem” you’re dealing with. If I’m understanding everything correctly, the piece of the puzzle that is missing, is updating the generic annotations family with some of the .json custom data.

The first thing that came to my mind - how are you linking the generic annotation family in Revit with the data from the json file for the update to take place?

Hey @bjoern, thanks for your quick reply!

Updating the family with the generated .json data is indeed the missing piece of this puzzle!

If I understand your question correctly, I am trying to link the data in the same way as I would do in Grasshopper (perhaps this is where it’s going wrong), by providing the Family name, and type (found in the .json), which I think would look like something like this in Grasshopper:

In this case there is no geometry to send to Revit, only data, so I can’t use any of the SSO objects within GH.

So this is what I thought would do about the same thing as the grasshopper component:

# Add family and type information
speckle_object['family_name'] = data["family_name"]
speckle_object['type_name'] = data["type_name"]
speckle_object['category'] = "Generic Annotations"  # Ensure the category is set to Generic Annotations

I hope that’s an answer to your question!

Something I just noticed, what could possibly help understanding the issue and find a solution better:
I’ve just changed a setting inside Speckle Revit, where I put “Missing Type Mapping” to “Always”. Trying to receive the data after changing the setting, shows that there is no Type coming in at the first place:

Okay, right. I think we’re getting to the bottom of this :cool_spockle: . Could you send the Revit model with revit families to the same project you linked (maybe under a new model) (it’s ok if there’s no geometry). I just want to inspect the families you’re targeting.

Cool! I’ve sent a chunk of the family to the following model: speckle team test - Test Data Python > Revit | Speckle

1 Like

For the “updating” to work properly, we need to target the same object structure as well as the proper applicationId of the object we want to update.

Instead of investing a lot of time into updating the .json structure, how about:

  • Receiving the information from speckle team test in Python using specklepy
  • Doing some changes to the desired values in Python
  • Sending whole (updated) commit back to the same model
  • Test receiving that updated commit back in Revit where the original family came from and see if the family updated.

Some help on receiving and deserializing a model can be found here. Note some of the parameters may be different depending on the specklepy version you are working with (but the flow required remains the same).

Let me know if that works! If so, we can then see how this fits into your workflow (bigger picture) and make it work in the original .json → Speckle → Revit approach.

1 Like

Hey @Zacheyre_RHDHV, checking in on how this is going :slight_smile:

Hey @bjoern, hope you had a great weekend!

I’ve been playing around with your suggestion and did manage to (only) change the “value” parameter within the “8LOA” object (new value is 123) (found in updated parameters - Test Data Python > Revit | Speckle) :
image

Now the sad part is, that when it comes to receiving the updated commit back to Revit, it doesnt update the values inside of the family :frowning:

Any idea on how to proceed?

PS: Only thing thats different is “id”

(haha, while writing this, I just see you checking in, thank you for that :slight_smile: )

1 Like

The id is expected, this is a speckle thing and is generated when serializing :slight_smile: . I assmue, that speckle team test model receives information from Revit, and updated parameters model receives updated paramter from the speckle team test model through a little python action?

Under this assumption, I have put the two models side by side and compared in dev mode. (Left being recieved from Revit, right being updated from python). The applicationId is the same which is good! This is from the hostApp (Revit in your case). The link between “old” and “new” should be established. However, you noted no updated. So, what could be happening :thinking:

I notice, that the structure has changed a bit and the speckle_type for example changes. Could you change your python script around to purely mutate the received commit (maintain commit received from operations.receive and just change a few values). i.e. look to minimize instantiating and assigning of new variables, but just edit the original commit.

First of all: your assumption is correct!

I’ve tried you suggestion, but haven’t had any luck with updating the family within Revit.

Just to clarify: I used the “Selection” id first and changed the parameter within this structure first.
Now, after changing up the script with your comment, I’ve used the “speckle team test” id, and managed to change only this “8LOA” value parameter. Now, the parameter within the “updated parameters” id is changed, still nothing happens in Revit sadly.

Only thing I notice, is that when sending back the data from python, the “units” are added and the totalChildrenCount goes from 0 to 4. - This also happens when I don’t change the parameters and just receive the data and immediatly send it back to the “updated parameters” stream…

Hey @bjoern,

Just reaching out to you to see if you had any idea on how to proceed on this!

Hi @Zacheyre_RHDHV, @bjoern is taking a deserved break right now - I’ll pick this up and see if I can track down with you why this hasn’t worked - bear with me as I get up to speed.

1 Like