Hi @izzylys,
i ve watched your tutorial on how to create a revit beam via python. thanks!
could you kindly extend your example and show how to create a Revit Wall and Revit Window object via SpecklePy?
Could you provide a reference document of all attributes and types that exist in speckle and their
parameters? e.g. Revit Beam, Revit Steel Beam, ArchiCAD Wall etc..
Since you define the Revit Wall type here, are those types also understood by ArchiCAD?
Im receiving the following error when executing the Script multiple times. Perhaps you know how to solve it too
ValueError: The speckle_type: Objects.BuiltElements.Level is already registered for type: Level. Please choose a different type name.
we managed to go around question #4 with the following functions… but maybe not ideal.
cheers, matthias
def get_fully_qualified_name(cls):
return f"{cls.__module__}.{cls.__qualname__}"
keys_to_remove = []
for key, value in _RegisteringBase._type_registry.items():
print(key, value)
if get_fully_qualified_name(value).startswith("kumiki"):
keys_to_remove.append(key)
for key in keys_to_remove:
stype = _RegisteringBase._type_registry.get(key)
if stype:
del _RegisteringBase._type_registry[key]
Sorry about late reply. Let’s go over your questions.
Unfortunately, I can’t provide you a document that shows all the classes Speckle has, but even better, I can provide you the source code. You can find all the types and attributes here.
For creating custom objects with Specklepy, using these references, I’ll attach some examples below.
Here how you can create a RevitBeam:
from specklepy.objects import Base
from specklepy.objects.geometry import Line, Point
from specklepy.api.wrapper import StreamWrapper
from specklepy.api import operations
from typing import List, Optional
class Level(Base, speckle_type="Objects.BuiltElements.Level"):
"""
A custom Level class
"""
name: str = None
elevation: float = None
def __repr__(self) -> str:
return f"Level(id: {self.id}, name: {self.name}, elevation: {self.elevation})"
class RevitBeam(
Base, speckle_type="Objects.BuiltElements.Revit.RevitBeam", detachable={"level"}
):
"""
A custom RevitBeam class
"""
family: str = None
type: str = None
baseLine: Line = None
level: Level = None
units: str = None
displayValue: list = None # List[Mesh]
parameters: Base = None
elementId: str = None
def __repr__(self) -> str:
return f"RevitBeam(id: {self.id}, family: {self.family}, type: {self.type}, level: {self.level}, baseLine: {self.baseLine})"
# Create a level
level = Level(name="Level 0", elevation=0)
# Create a beam
beam = RevitBeam(
family="Structural Framing",
type="UB305x165x40",
level=level,
baseLine=Line(start=Point(x=0, y=0, z=0), end=Point(x=4, y=10, z=0)),
units="m",
)
# Create commit object
commit_obj = Base()
commit_obj["@revit beam from python"] = beam
# Send to Speckle
wrap = StreamWrapper(
"<YOUR_URL>"
)
client = wrap.get_client()
transport = wrap.get_transport()
obj_id = operations.send(commit_obj, [transport])
client.commit.create(wrap.stream_id, obj_id)
print(f"Successfully sent beam with ID: {obj_id}")
You’ll only see a base line in the viewer, but if you receive in Revit, this will create a Revit Beam for you.
@dogukan Thanks for the reply. I was trying to query objects using the new Speckle Connector v3 in Revit and Archicad, but I wasn’t able to retrieve any native wall objects, except the base line. It works fine with the previous v2 connectors though. I also tried the v3-dev branch on specklepy.
Thanks a lot,
Matthias
Speckle project link:
Example code I’m using:
from typing import List
from specklepy.objects import Base
from specklepy.objects.geometry import Line, Point
from specklepy.api import operations
from specklepy.api.client import SpeckleClient
from specklepy.api.wrapper import StreamWrapper
from specklepy.objects.base import Base
from dotenv import load_dotenv
import logging
import os
# Load environment variables
load_dotenv()
LOG = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
# Get config from .env
SPECKLE_HOST = os.getenv("SPECKLE_HOST")
SPECKLE_TOKEN = os.getenv("SPECKLE_TOKEN")
STREAM_ID = os.getenv("STREAM_ID")
# -- Speckle-Compatible Classes --
class Level(Base, speckle_type="Objects.BuiltElements.Level"):
name: str = None
elevation: float = None
class Wall(Base, speckle_type="Objects.BuiltElements.Wall"):
family: str = None
type: str = None
baseLine: Line = None
level: Level = None
height: float = None
units: str = "meters"
# -- Input Wall Format --
class CTWall:
def __init__(self, p1: Point, p2: Point, height: float):
self.p1 = p1
self.p2 = p2
self.height = height
# -- Conversion Function --
def create_wall_from_ctwall(ct_wall: CTWall) -> List[Wall]:
level = Level(name="Level 1", elevation=0) # Must match Revit level
wall = Wall(
family="Basiswand",
type="Ziegel+WD hart 300+160", # Must match a valid Revit wall type
baseLine=Line(start=ct_wall.p1, end=ct_wall.p2),
level=level,
height=ct_wall.height,
units="meters",
)
return [wall]
# -- Commit to Speckle --
def send_to_speckle(ct_wall: CTWall, speckle_client: SpeckleClient, stream_id: str):
walls = create_wall_from_ctwall(ct_wall)
commit_obj = Base()
commit_obj["walls"] = walls
# Transport setup
wrapper = StreamWrapper(f"{SPECKLE_HOST}/streams/{stream_id}")
transport = wrapper.get_transport()
try:
object_id = operations.send(commit_obj, [transport])
speckle_client.commit.create(
stream_id=stream_id,
object_id=object_id,
branch_name="main",
message="Cadwork: Sending wall element to Revit",
)
print("âś… Wall successfully sent to Speckle stream:", stream_id)
except Exception as e:
LOG.error("❌ Failed to send to Speckle: %s", e)
# -- Main entrypoint --
if __name__ == "__main__":
start = Point(x=0, y=0, z=0)
end = Point(x=5, y=0, z=0)
wall = CTWall(p1=start, p2=end, height=3.0)
# Authenticated client
client = SpeckleClient(host=SPECKLE_HOST)
client.authenticate(token=SPECKLE_TOKEN)
if not STREAM_ID:
raise ValueError("Missing STREAM_ID environment variable.")
send_to_speckle(wall, client, STREAM_ID)