IUpdater for duct system and fill in parameter

Anonymous

IUpdater for duct system and fill in parameter

Anonymous
Not applicable

Hello forum

 

I am stuck with the IUpdater, the problem I am facing is that I do not know how to add my trigger.

If the parameter (Duct System Abbreviation) as showed in the screenshot changes on any object (element) I would like to trigger the IUpdater and fill in another parameter which I created.

 

OnStartUp:

 

       public Result OnStartup(UIControlledApplication application)
        {
            DuctSystemUpdater updater = new DuctSystemUpdater(application.ActiveAddInId);
            UpdaterRegistry.RegisterUpdater(updater);

            ElementClassFilter systemFilter = new ElementClassFilter(typeof(MEPSystem));

            // Add trigger, if duct system parameter is filled in. Trigger.
            UpdaterRegistry.AddTrigger(updater.GetUpdaterId(),
                                       systemFilter,
                                       Element.GetChangeTypeAny());

 

This is how I am doing this right now, this should check everything in MEPSystem. So the ducts 🙂

 

OnShutDown:

        public Result OnShutdown(UIControlledApplication application)
        {
            DuctSystemUpdater updater = new DuctSystemUpdater(application.ActiveAddInId);
            UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
            return Result.Succeeded;
        }

 

 

As for the updater itself:

 

    public class DuctSystemUpdater : IUpdater
    {
        public static bool m_updateActive = false;
        private AddInId addinID = null;
        private UpdaterId updaterID = null;
        public DuctSystemUpdater(AddInId id)
        {
            addinID = id;
            updaterID = new UpdaterId(addinID, new Guid("5C58B001-B9BD-4E56-8770-858A905F29D0"));
        }
        public void Execute(UpdaterData data)
        {
            Document doc = data.GetDocument();

            ElementClassFilter systemFilter = new ElementClassFilter(typeof(MEPSystem));
            ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_DuctSystem);
            LogicalAndFilter ductSystemFilter = new LogicalAndFilter(systemFilter, filter);

            // Apply the filter to the elements in the active document
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            IList<Element> systems = collector.WherePasses(ductSystemFilter).ToElements();

            foreach (MEPSystem ms in systems)
            {
                foreach (Element element in ms.Elements)
                {
                    // Add new parameter to each element
                    // Add 4 options through a case
                    Parameter paraValue = element.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM);
                    string sParameter = paraValue.ToString();

                    Parameter p = element.LookupParameter("AE calc");
                    p.AsValueString();

                    

                    switch (sParameter)
                    {
                        // W5700_Luchtbehandeling, retour // M570R
                        case "M570R":
                            p.Set(1);
                            break;

                        // W5700_Luchtbehandeling, toevoer // M570F
                        case "M570F":
                            p.Set(2);
                            break;

                        // W5700_Luchtbehandeling, uitblaaslucht buiten // M570E
                        case "M570E":
                            p.Set(3);
                            break;

                        // W5700_Luchtbehandeling, aanzuiglucht buiten // M570A
                        case "M570A":
                            p.Set(4);
                            break;
                            // Breaking out of the case if parameter is not like cases above.
                        default:
                            Console.WriteLine("Case does not match.");
                            break;

                    }
                }
            }
        }
        // Copy pasta from the internet, else it gives exceptions
        public string GetAdditionalInformation()
        {
            return "N/A";
        }
        public ChangePriority GetChangePriority()
        {
            return ChangePriority.FreeStandingComponents;
        }
        public UpdaterId GetUpdaterId()
        {
            return updaterID;
        }
        public string GetUpdaterName()
        {
            return "ParameterUpdater";
        }
    }

 

 

I am not getting this to work, does anybody also know how you can view the trigger in the code if it works or not? If somebody can help me with parameters or code on how to actually debug or follow a along as this runs because I do not know to follow the code. Or force the executer.

 

 

Thanks in advance

Greetings

Sebastiaan

0 Likes
Reply
1,213 Views
12 Replies
Replies (12)

jeremy_tammik
Autodesk
Autodesk

Your approach looks fine at first glance.

 

However, are you absolutely certain that the abbreviation that you are interested in is really stored in a parameter on the MEPSystem element?

 

If you are uncertain, then please determine the exact location storing this abbreviation data. Most importantly, you need to know the Revit element class in order to construct an appropriate trigger for it.

 

To step through the code line by line, you can set a breakpoint in the Visual Studio debugger. However, just as you say, this will not help much if the code is never executed.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open

Anonymous
Not applicable

Hello Jeremy thanks for replying.

 

Was guessing i could get that info from MEPSystem going of a previous post on your blog. https://thebuildingcoder.typepad.com/blog/2013/02/simple-mep-system-traversal.html

 

However when using RevitLookUp, i discovered that it is in MEPCurve as property: MEPSystem, so I was sort of guessing in the right direction.

 

        public void Execute(UpdaterData data)
        {
            Document doc = data.GetDocument();

            ElementClassFilter systemFilter = new ElementClassFilter(typeof(MEPCurve));
            ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_DuctCurves);
            LogicalAndFilter ductSystemFilter = new LogicalAndFilter(systemFilter, filter);

            // Apply the filter to the elements in the active document
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            IList<Element> systems1 = collector.WherePasses(ductSystemFilter).ToElements();

            foreach (MEPCurve ms in systems1)
            {
                foreach (Element element in ms.Elements)
                {

So I am editing this into my code but can't use ms.Elements, dont' know how to work around this in my code so it loops through everything. Input would be appreciated. I feel I am getting closer each day 🙂

 

 

Greetings

Sebastiaan

0 Likes

Anonymous
Not applicable

.OnStartUp

 

  ElementClassFilter systemFilter = new ElementClassFilter(typeof(Duct));

 

 

Execute

               Document doc = data.GetDocument();

                FilteredElementCollector collector = new FilteredElementCollector(doc);
                ElementClassFilter ductSystemFilter = new ElementClassFilter(typeof(MEPSystem));


                // Apply the filter to the elements in the active document
                IList<Element> systems1 = collector.WherePasses(ductSystemFilter).ToElements();

 

I can read the values of the system type with this. And changing it around to MechanicalSystem typeof can get the writing of the other parameter I need to work. However I can not seem to combine both of these, so reading the value and writing in 1.

 

0 Likes

FAIR59
Advisor
Advisor

You can filter for FamilyInstances and only trigger on a change of the [ BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM ] parameter.

ElementClassFilter classfilter = new ElementClassFilter(typeof(FamilyInstance));
UpdaterRegistry.AddTrigger(this.m_updaterId,doc, classfilter, Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM)));

In the Execute method you get only the instances where the abbreviation is changed , no additional filtering required !

foreach(ElementId id in data.GetModifiedElementIds())
{
    FamilyInstance inst = data.GetDocument().GetElement(id) as FamilyInstance;
    // your code to cahnge the [ AE calc ] parameter
}

  

 

Anonymous
Not applicable
Hello
Thanks for helping me out, however I am stuck how exactly you get the trigger in the onstartup. How do you get the doc working?
0 Likes

FAIR59
Advisor
Advisor

In the onstartup you can only add a trigger that works for all documents. (without the Document-parameter )

UpdaterRegistry.AddTrigger(upd.m_updaterId, classfilter, Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM)));

 to add a trigger for a document you need to subscribe to the documentopened-event:

public Autodesk.Revit.UI.Result OnStartup(UIControlledApplication application)
{
   application.ControlledApplication.DocumentOpened += ControlledApplication_DocumentOpened;
}

private void ControlledApplication_DocumentOpened(object sender, Autodesk.Revit.DB.Events.DocumentOpenedEventArgs e)
{
   Document doc = e.Document;
   // add trigger for document
}

 

Anonymous
Not applicable

Hello thanks for responding so quickly.

 

I had to use RBS_DUCT_SYSTEM_TYPE_PARAM because for some reason the abbreviation returns blank over all the elements. The trigger however, i changed it to Element.GetChangeTypeAny()); and it does not trigger after every duct that is drawn. It does get the duct fittings and connection pieces but the main ducts stay empty. I am currently debugging and trying to fix it.

 

Figuring this has to do with the ElementClassFilter at the startup.

 

 

Your previous post helped me enormously by the way.

0 Likes

Anonymous
Not applicable
Sorry for spamming a bit. It seems to get every corner and twist in the duct system but not the ducts itself. It skips these in the elementID loop. Also the trigger is really weird and sometimes works and sometimes doesn't, changed it to ChangeTypeAny() to be sure it gets everything.
0 Likes

FAIR59
Advisor
Advisor

My bad, Ducts and FlexDucts aren't FamilyInstances ( placed instances of User-Families.). 

To also catch the ducts you need to make an ElementMulticlassFilter including the MEPCurve-type ( parent of Duct and FlexDuct ) .

List<Type> typeList = new List<Type>();
typeList.Add(typeof(FamilyInstance));
typeList.Add(typeof(MEPCurve));
ElementMulticlassFilter multiClassfilter = new ElementMulticlassFilter(typeList);
UpdaterRegistry.AddTrigger(upd.m_updaterId, multiClassfilter, Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM)));

Do not cast the elements to FamilyInstance anymore, in the execute loop of the Updater , as  Ducts and FlexDucts aren't FamilyInstances.

Anonymous
Not applicable

I am just going to keep asking if you do not mind. I am testing this and it does work, sort of.

When I add new ducts. if the duct is changed from size or has something added to it the value is written. This means the last duct i have drawn does not update to the value however when I change the length of it it gets the parameter written. However the fittings and angles stay empty as well but when I change the size of the duct connected to a fitting the fitting gets the parameter written.

 

I have changed the trigger to

           List<Type> typeList = new List<Type>();
            typeList.Add(typeof(FamilyInstance));
            typeList.Add(typeof(MEPCurve));
            ElementMulticlassFilter multiClassfilter = new ElementMulticlassFilter(typeList);

            UpdaterRegistry.AddTrigger(updater.GetUpdaterId(),
                           multiClassfilter,
                           Element.GetChangeTypeAny());

 

 

the execute looks like this.

                foreach (ElementId id in data.GetModifiedElementIds())
                {
                    Element inst = data.GetDocument().GetElement(id);
                    Parameter p = inst.LookupParameter("AE Calc");

                    switch (inst.get_Parameter(BuiltInParameter.RBS_DUCT_SYSTEM_TYPE_PARAM).AsValueString())
                    {

 

data.GetAddedElementIds()) does not seem to trigger anything. Seems really weird to be the way it is behaving.

0 Likes

FAIR59
Advisor
Advisor

you can define more then one trigger for your Updater. Add a second trigger to registry .

UpdaterRegistry.AddTrigger(upd.m_updaterId, multiClassfilter, Element.GetChangeTypeElementAddition());

 

0 Likes

Anonymous
Not applicable

Excuse me for the late reply.

 

This still didn't fix the problem after a few evenings and nights of trying different triggers and changing code around,  I have given up on trying to get this working and am trying something different . Appreciate the feedback and code a ton!!

 

 

0 Likes