Skip to main content
Niagara Community
Content Starts Here
michaelbmichaelb 

I was wondering if there was a way to animate the visible property of a Px layer. Now, I already know I could animate the individual objects that I would like to hide/show, and I could also put the dynamic objects in a PxInclude and animate that object, but that makes for a maintenance nightmare in some situations.

 

What I would specifically like to do is to create a separate layer, and then dynamically turn that layer on and off using Boolean Writable in the component space. I don't know of any way to link a component space object to an xml property that exists in the filespace (if only it were that simple...), so I was thinking of maybe using an xml variable to serve as a proxy for the status value in the layer declaration, and then use the xml equivalent of an IF/THEN to change the value of that variable from normal to hidden based on the out.value queried from the boolean object..Is this even possible?

Thinking out loud....

<xls:variable layerState="normal"></xls:variable>

<IF (ord path to boolean out.value property) = "true">

      layerState="normal"

<ELSE>

     layerState="hidden"

</ELSE>

</IF>

<layer name="DescLayer" state={layerState}>

.....

 

I know this doesn't work, but does the idea itself have promise?

 

Thanks for any advice!

 

Best Answer chosen by michaelb
michaelbmichaelb

Nevermind...It appears that the layers are only useful while EDITING Px graphics...They are useless while viewing a Px graphic.

MnoehrMnoehr 

Hello NC.

I am rather new to the Niagara Framework, and I'm having difficulty doing, what seems to be a rather simple operation.

I have this sidenav bar, and on that, I want to disable certain buttons (not hide), when the user isn't an admin.

What I've done, is create the button, and set the degradeBehavior to "Disable", but what Ord can I select, that would show or give a valid value to do this?
In the SCADA world, its something like securityAccessLevel or groupAccessLevel.

Best regards,
Michael

Best Answer chosen by Mnoehr
JamesJames (Tridium) 
You didn't mention which version of Niagara you are using and there are some slilght differences between AX and N4.

There is a category service in the station which allows browsing components in the station, histories, files, etc. You can assign things to different defined categories.

When you look at the slot sheet view of a component there is an operator flag which may be checked. If the operator flag is checked that means operator level permissions are required to access the object and if not checked that means admin level permissions are required to access the object.

In AX permissions are assigned to individual users. In N4 permissions are assigned to roles and one or more roles are assigned to each individual user. Permissions are broken down into two main levels being operator and admin, which relate to the operator slot flag. Operator and admin levles are broken down further into read (r), write (w) and invoke (i). 

The ord for your button should reference a component in the station which does not have the operator slot flag set, meaning it requires admin level permissions.

In Workbench you can press Ctrl + L and paste in this link, module://docSecurity/doc/sta_CategoriesRolesAndUsers.html#sta_CategoriesRolesAndUsers , which is for the help topic in N4 Workbench that will provide more details.
jlenertzjlenertz 

I have seen this issue across multiple JACEs with different versions of Niagara. My current JACE is 3.8.41 and running a lon network where all communication and polling/busy time, etc. looks normal.

However, every couple months or so, the LON1 driver will fail ping to all devices, and not be able to successfully ping those devices until I reboot the JACE.

Does the JACE have a "fail driver" condition where, if it cannot keep up due to too many COV updates it fails the driver? What is the general problem here? console.txt and spy logs just show a bunch of failed responses, nothing particularly useful.

Best Answer chosen by jlenertz
jlenertzjlenertz

I can't speak for Tridium, but what I've heard is that some of the updates since that revision have attempted to fix this condition. 3.8.213 should not do this.

 

However there is also a good way of avoiding this scenario entirely, and that is through careful construction of the lon network physically and management on the lon network driver property sheet. In general, leave non-critical values as poll-only. You can actually have all links set to poll-only, just make sure all the NVs you need to write periodically are set to a tuning policy that has a max write time significantly lower than that NVs max receive time. Otherwise you'll bounce NVs. As well, make sure all of your COV subscription NVs have a min send time at a reasonable level (10-30 seconds I would think) so they can't bomb your network with changes from 72.1 to 72.3 etc. Last, make sure your poll time is high enough to that busy time is less than 75%. With a properly tuned set of driver settings and a decent Niagara revision (not 3.7.106), you should be fine.


Of course you can have too many NVs or controllers on the network either. If you're using Distech ECLs I wouldn't go above 40 or so even with all the above precautions.

 

In the past we shied away from using poll-only because we thought this would prevent writing at the max write time, but Tridium has corrected us that as long as your NVs are set to the corresponding tuning policy you're fine. That said you have to make sure when you do a new NV (for example sharing a thermostat) making sure you go in and manually change the tuning policy on that NV.

pomerojapomeroja 

Is there anyway to query all points marked with a particular dictionary?

i have tried everything i can think of...

station:|slot:/Schedules|neql:u

station:|slot:/Schedules|neql:u:* (fails miserably)

any ideas?

Best Answer chosen by pomeroja
JamesJames (Tridium) 

I don't think that NEQL is designed for that sort of thing. Even if you could write a NEQL query to use a wildcard for any tag from a particular dictionary, the results would just be a table of the entities. It wouldn't tell you what specific tags were applied to each entity, so I don't think that the results would really be that useful.

There may be some other way but the first thing that comes to mind is to use the robot editor view to iterate through the station and check for components with tags from the particular dictionary.

 

// depends: baja; program; tagdictionary

import javax.baja.sys.*;
import com.tridium.program.*;
import javax.baja.tagdictionary.*;
import javax.baja.tag.util.*;
import javax.baja.tag.*;
import javax.baja.collection.*;
import java.util.Collection;
import java.util.Iterator;

public class RobotImpl
  extends Robot
{

  public void run()
    throws Exception
  {
    process(Sys.getStation());
  }

  public void process(BComponent c)
    throws Exception
  {
    if(c instanceof BTagDictionaryService) return;
    
    String msg = c.getSlotPath().toString();
    
    Tags tags = c.tags();
    
    Collection<Tag> collection = tags.getAll();
    Iterator<Tag> it = collection.iterator();
    
    while(it.hasNext())
    {
      Tag tag = it.next();
      String nameSpace = tag.getId().getDictionary();

      // "hs" below checks for haystack dictionary, change to desired dictionary name space
      if(nameSpace.equals("hs"))
      {
        msg = msg + "," + tag.getId() + "=" + tag.getValue();
      }
    }
    
    log.println(msg);
    
    // recurse
    BComponent[] kids = c.getChildComponents();
    for(int i=0; i<kids.length; ++i)
      process(kids[i]);
  }
}

 

It would probably be better to use a slight variation of the code as a custom BQL scalar function. That way you could just use a BQL query and in the projection specify the BQL scalar function which could return the tags for the specified dictionary.

chowardchoward 

I can't seem to get one of my programs ("XenAmpCalc") to show up in the palette.  It compiles with no errors and the other programs show up fine in the palette.  I believe I have the module.palette and module-include.xml correct, but "XenAmpCalc" doesn't show up. Any ideas on where to look for a problem?

excert from module-include.xml

<type class="com.xencom.xenToolbox.BXenTabularConverter" name="XenTabularConverter"/>
<type class="com.xencom.xenToolbox.BXenTotAvg" name="XenTotAvg"/>
<type class="com.xencom.xenToolbox.BXenAmpCalc" name="XenAmpCalc"/>

 

excert from module.palette

<!-- /Math -->
 <p n="Math" t="b:Folder">
  <!-- /Math/XenTabularConverter -->
  <p n="XenTabularConverter" t="xtb:XenTabularConverter"/>

    <!-- /Math/XenAmpCalc -->
    <p n="XenAmpCalc" t="xtb:XenAmpCalc"/>

     <!-- /Math/XenTotAvg -->
     <p n="XenTotAvg" t="xtb:XenTotAvg"/>
 </p>

 

Best Answer chosen by choward
chowardchoward

After much combing of my code and also trying James' suggestions, I finally found my issue.  In the slotomatic code, I had specified "amp" instead of "ampere" in the BFacets.UNITS.

facets =
        {
                @Facet(name = BFacets.UNITS, value="UnitDatabase.getUnit(\"ampere\")"),
                @Facet(name = BFacets.PRECISION, value="1")
        }

Slotomatic didn't catch it, and no errors were thrown when building the .jar file.  There were also no errors in the console.  It just would not show up in the palette.

gbutton-brandtgbutton-brandt 

Hi all,

I'm sure this has been asked or tried before, but I wasn't seeing anything posted out there. Is it possible to execute actions on control points in a station via the program service (preferably) or the robot editor?

Asking specifically about niagara proxy points pulled into a supervisor from other stations, although it would be useful to know for points native to a station as well.

N4 supervisor is at 4.2.36.34.

Any thoughts or help would be appreciated. Thank you,

Gavin

Best Answer chosen by gbutton-brandt
JamesJames (Tridium) 
The batch editor allows setting the fallback value which is essentially the same as invoking a set action. However, there are no options to invoke specific actions on components using the batch editor.

You can use the robot editor to resolve some comonents and iterate through them invoking the desired action. The below example overrides some specific numeric points for 1 hour to a desired value.

// depends: baja; program; control

import javax.baja.sys.*;
import javax.baja.naming.*;
import javax.baja.collection.*;
import javax.baja.control.*;
import javax.baja.control.util.*;
import com.tridium.program.*;

public class RobotImpl
  extends Robot
{

  public void run()
    throws Exception
  {
    BOrd qord = BOrd.make("station:|slot:/Drivers/BacnetNetwork|bql:select * from control:NumericWritable where name='OccCoolStpt'");
    BITable result = (BITable)qord.resolve().get();
    Cursor c = result.cursor();
    BNumericWritable point;
    BNumericOverride override = new BNumericOverride(BRelTime.makeHours(1), 78.0);
    
    while(c.next())
    {
      point = (BNumericWritable)c.get();
      point.invoke(point.getAction("override"), override);
      log.println(point.toPathString() + " - override value to 78 for 1 hour");  
    }
  }
}

 
GingerNinjaGingerNinja 

I am currently working my way through the various tutorials and examples to create custom Modules. I am trying to get my newly created Widget (TestWidget) to display on the Px Graphic. It is intended to be WebWidget. I use the "ExampleLinearGauge" from the docDeveloper Module as an example. 

I have gotten to the point where i have a module within my workbench, I can build it, it will show up and be usable within my palette. and i Can set the WebWidget and drop it to the Px Page. 

I essentially copied the code from the bajascript "Getting Started" example. and Used the "BajaScriptExamples" Components Folder and the "BajauxExamples/MyFirstWidget" as reference for my source Javascript. 

My problem is that the WebWidget does not display. It just renders an HTML error 500: Problem accessing /bajaux/webwidget/view:TestUX:TestWidget. Reason:

    Start of exception is:

        javax.baja.sys.TypeNotFoundException: TestUX:TestWidget

I found another example on this forum for an "htmlnavmenu" example. When i compile and load this example i get the same error that the type is not found.  

If i load my JavaScript in a JsPlayground, everything works fine. 

My immediate guess is that the syntac of my Js Property on my Widget is incorrect, or that i missed something in the .java file. 

Here is my file structure:


-TestUX

   --.gradle

   --TestUX-ux

      ---.gradle

      ---build

      ---src

          ----com

               -----company

                     ------ux

                        --BTestWidget.java

          ----rc

              TestWidget.js

      ---build.gradle

      ---module-include.xml

      ---module.lexicon

      ---module.palette

         ---TestWidget


My Java for BTestWidget.java:

package BTestWidget;

import java.util.*;              /* java Predefined*/
import javax.baja.nre.util.*;    /* nre Predefined*/
import javax.baja.sys.*;         /* baja Predefined*/
import javax.baja.status.*;      /* baja Predefined*/
import javax.baja.util.*;        /* baja Predefined*/
import javax.baja.naming.*;
import javax.baja.web.js.BIJavaScript;
import javax.baja.web.js.JsInfo;
import javax.baja.web.*;


public final class BTestWidget
    extends BSingleton
    implements BIJavaScript, BIFormFactorMax
{
  private BTestWidget() {}
  public static final BTestWidget INSTANCE = new BTestWidget();

  @Override
  public Type getType() { return TYPE; }
  public static final Type TYPE = Sys.loadType(BTestWidget.class);

  public JsInfo getJsInfo(Context cx) { return jsInfo; }

  private static final JsInfo jsInfo =
      JsInfo.make(BOrd.make("module://TestUX/rc/TestWidget.js"));
}


My Javascript for TestWidget:

/**
 * A module defining `TestWidget`.
 *
 * @module nmodule/myFirstModule/rc/TestWidget
 */
define(['bajaux/Widget',
        'bajaux/mixin/subscriberMixIn'], function (
        Widget,
        subscriberMixIn) {

  'use strict';

  /**
   * Description of your widget.
   *
   * @class
   * @extends module:bajaux/Widget
   * @alias module:nmodule/myFirstModule/rc/TestWidget
   */
  var TestWidget = function () {
    Widget.apply(this, arguments);
    subscriberMixIn(this);
  };

  //extend and set up prototype chain
  TestWidget.prototype = Object.create(Widget.prototype);
  TestWidget.prototype.constructor = TestWidget;

  /**
   * Describe how your widget does its initial setup of the DOM.
   *
   * @param {jQuery} jq The DOM element into which to load this Widget
   */
  TestWidget.prototype.doInitialize = function (jq) {
    jq.html('<input type="text" value="value goes here" />');
  };

  /**
   * Describe how your widget loads in a value.
   *
   * @param {baja.Component} ramp The ramp component loaded into the widget.
   */
  TestWidget.prototype.doLoad = function (ramp) {
    var input = this.jq().find('input');

    function update() {
      input.val(ramp.getOut().getValueDisplay());
    }

    // Call update whenever a Property changes
    this.getSubscriber().attach("changed", update);

    // Call update for the first time.
    update();
  };

  return TestWidget;
});


 

In the configuration of the Web Widget i have the property of Js set to : view:TestUX:TestWidget

I am assuming my problem is somewhere between the .java not registering something (im not sure what it does). OR that the ORD i used on the Js property is syntactically wrong. 

I put some print statements in the BTestWidget.java constructor and noticed nothing got printed to the Application Director (although im not sure if that is where it would be directed). Is there a way to "Register" my Widget? is that what i am missing?

Any help would be great. Thank you. 

Best Answer chosen by GingerNinja
GingerNinjaGingerNinja

I Figured it out. I had a feeling it was something stupid, and it was. 

For those that ever have the same problem. Ill explain. 

I tried loading my modules to my Remote Station. The Boot logs in the Application Director indicated a Severe error that my widgets had "no class" when trying to register. 

I then double checked some simple things. My file path and package of my .java. 

If you look in my previously posted code, my package is just the Class name. I changed this to "com.company.ux". I also had a space ' '  in my company folder name, i removed this just to be safe but wasnt sure if that caused an issue. 

So what i learned is to pay close attention to the path. 

jlenertzjlenertz 

I have a program that runs through a station and renames a proxy extension's pointID based on finding nodes of a specific type. What I would like to do is find nodes of a specific type AND nodes that start with a string like HP (search would be where displayName is like HP*).

This is easy to do with BQL, but how do I do this when I am using a slot cursor to run through the station?

public void onExecute() throws Exception                                                
{
  BComponent p = getProgram().getParent().getParentComponent();
 
       
   SlotCursor sc = p.getProperties();
   System.out.println("Running");  
    while(sc.next())
    {  

      if (sc.slot().asProperty().getType().getTypeSpec() == getType())
      {
      
        BComponent a = (BComponent) sc.get();
        BComponent b = (BComponent)a.getNavChild("RelaySts");               
        BNiagaraProxyExt c = (BNiagaraProxyExt)b.getNavChild("proxyExt");
        
        BComponent f = (BComponent)a.getNavParent(); //HOA
        BComponent g = (BComponent)f.getNavParent(); //points
        BComponent h = (BComponent)g.getNavParent(); //NodeName
        
        String TripleParent = h.getName();
        String parent = a.getName();
        
        
        c.setPointId(TextUtil.replace(c.getPointId(), "HP1N", TripleParent));
        c.setPointId(TextUtil.replace(c.getPointId(), "SupplyFan", parent));  
      }
      }
    }

 

Best Answer chosen by jlenertz
JamesJames (Tridium) 
You should be able to get the name of the component you are checking as a string and then use the startsWith() method.

if(comp.getName().startsWith("HP"))
YevgenyYevgeny 

I would like to build px file, which could reference different numeric points, depending of the current user.

For example I could create 3 numeric points called timePeriod, each under its user, like that:

UserService

  • Alice
    • timePeriod
  • Bob
    • timePeriod
  • Charlie
    • timePeriod

So now Alice could have own preferred timePeriod (1 month) and Bob will have his own (1 year).

Now I would like to display this point value on px, using binding ord like /UserService/%username%/timePeriod (this binding does not work, obviously). So it could point to a different value, depending on which user is logged in.

Is it possible?

 

Best Answer chosen by Yevgeny
JamesJames (Tridium) 
In BFormat syntax %user()% will display the user's name.

In client side Java code, if you have the context there is a 'username' facet normally availalbe in the context.

In client side hx code, op.getUser() should resolve the user.

Unfortunately you aren't going to be able to use any of those in the ord property of a binding. At least not unless you are creating your own binding and doing something to process the BFormat syntax when resolving the ord.