HVAC-Talk: Heating, Air & Refrigeration Discussion banner

Niagara 4 setting a NumericWritable

Tags
java niagara
2.1K views 8 replies 3 participants last post by  cljohnson3rd  
#1 ·
Hi, was looking for some help.
I have an ORD which I can get the value of in code but I can’t find how to set a value to that ORD.
The ORD points to a NumericWritable point on my wiresheet, I am taking JSON (Ord & Value) on my program block’s input and want to write the value to the Ord, I am able to decode the JSON ok but applying the value to the NumericWritable point is proving more difficult.

Thanks in advance all.
Happy Christmas!!
 
#3 · (Edited)
also...

Hi Synyster,

Thanks for the offer to help, I am a beginner with Niagara Java.
I have got this far and am able to get the info shown at the bottom of the post in my Application Director with the code below but I don't know what method I need to set the value of my Numeric Writable.

Here is my code...

public void onExecute() throws Exception
{
// execute code (set executeOnChange flag on inputs)



BOrd ordinSes = BOrd.make((String) getOrd()); //get the ORD from a string input pin
System.out.println("Ord = " + ordinSes);

double newVal = getNewValue(); get the value from a double input pin
System.out.println("New Value = " + newVal);

OrdTarget outValue = ordinSes.resolve();

BComponent bc = (BComponent)outValue.getComponent();
System.out.println("Ord Target = " + outValue);

BControlPoint bcp = (BControlPoint)outValue.get();

System.out.println("BControlPoint = " + bc);

Slot s = bc.getSlot("out");
System.out.println("slot = "+s);

BValue curVal = bcp.getOutStatusValue().getValueValue();
System.out.println("Current Value = "+ curVal);

BStatus curStatus = bcp.getOutStatusValue().getStatus();
System.out.println("Current Status = "+ curStatus);

Type type1 = bc.getType();

System.out.println("Type = "+ type1);

//bcp.setStatus(curStatus);

//bcp.set(BDouble.make(getValue()));

}

The lines I have commented out are my attempt to set the value to the Numeric Writable.

This is the output of the Application Director...

Ord = station:|h:22351
New Value = 11.0
Ord Target = station:|h:22351 -> 22.1 {ok} @ def
BControlPoint = 22.1 {ok} @ def
slot = out: baja:StatusNumeric
Current Value = 22.10
Current Status = {ok} @ def
Type = control:NumericWritable

What I intend to do is check if the vale has changed and if it has update my numeric writable, if not I will wait for the next update to the JSON inputs.
I also intend to check the status and if my target Numeric Writable is in Fault or Alarm set an output pin on my block to indicate this.

Again,

Thanks for any help you can provide me.

Added note: I have compiled my own basic modules and I would like to get this code into a module so if I need to do this in a different way please give me some simple pointers. Thanks.
 
#4 ·
Hi Synyster,

Thanks for the offer to help, I am a beginner with Niagara Java.
I have got this far and am able to get the info shown at the bottom of the post in my Application Director with the code below but I don't know what method I need to set the value of my Numeric Writable.

Here is my code...

public void onExecute() throws Exception
{
// execute code (set executeOnChange flag on inputs)



BOrd ordinSes = BOrd.make((String) getOrd()); //get the ORD from a string input pin
System.out.println("Ord = " + ordinSes);

double newVal = getNewValue(); get the value from a double input pin
System.out.println("New Value = " + newVal);

OrdTarget outValue = ordinSes.resolve();

BComponent bc = (BComponent)outValue.getComponent();
System.out.println("Ord Target = " + outValue);

BControlPoint bcp = (BControlPoint)outValue.get();

System.out.println("BControlPoint = " + bc);

Slot s = bc.getSlot("out");
System.out.println("slot = "+s);

BValue curVal = bcp.getOutStatusValue().getValueValue();
System.out.println("Current Value = "+ curVal);

BStatus curStatus = bcp.getOutStatusValue().getStatus();
System.out.println("Current Status = "+ curStatus);

Type type1 = bc.getType();

System.out.println("Type = "+ type1);

//bcp.setStatus(curStatus);

//bcp.set(BDouble.make(getValue()));

}

The lines I have commented out are my attempt to set the value to the Numeric Writable.

This is the output of the Application Director...

Ord = station:|h:22351
New Value = 11.0
Ord Target = station:|h:22351 -> 22.1 {ok} @ def
BControlPoint = 22.1 {ok} @ def
slot = out: baja:StatusNumeric
Current Value = 22.10
Current Status = {ok} @ def
Type = control:NumericWritable

What I intend to do is check if the vale has changed and if it has update my numeric writable, if not I will wait for the next update to the JSON inputs.
I also intend to check the status and if my target Numeric Writable is in Fault or Alarm set an output pin on my block to indicate this.

Again,

Thanks for any help you can provide me.

Added note: I have compiled my own basic modules and I would like to get this code into a module so if I need to do this in a different way please give me some simple pointers. Thanks.
Try this:

private BValue lastValue = null; // To store the last value
private boolean statusIndicator = false; // To track fault or alarm status

public void onExecute() throws Exception {
try {
// Retrieve the ORD from input pin
String ordInput = (String) getOrd(); // Replace with the actual method
BOrd ordinSes = BOrd.make(ordInput);
System.out.println("ORD: " + ordinSes);

// Retrieve the new value from input pin
double newVal = getNewValue(); // Replace with the actual method
System.out.println("New Value: " + newVal);

// Resolve the ORD to an OrdTarget
OrdTarget outValue = ordinSes.resolve();
BControlPoint bcp = (BControlPoint) outValue.get();

// Check if the value has changed
BValue curVal = bcp.getOutStatusValue().getValue();
if (lastValue == null || !lastValue.equals(curVal)) {
System.out.println("Value has changed. Updating Numeric Writable.");

// Update the Numeric Writable with the new value
bcp.set(BDouble.make(newVal));

// Update lastValue to the current value
lastValue = curVal;
} else {
System.out.println("Value has not changed. Waiting for the next update.");
}

// Check the status of the Numeric Writable
BStatus curStatus = bcp.getOutStatusValue().getStatus();
System.out.println("Current Status: " + curStatus);

// Update the status indicator if the target is in Fault or Alarm
if (curStatus.isFault() || curStatus.isAlarm()) {
statusIndicator = true;
setOutputPin("statusIndicator", true); // Update your block's output pin
System.out.println("Target is in Fault or Alarm. Status indicator set.");
} else {
statusIndicator = false;
setOutputPin("statusIndicator", false); // Clear the status indicator
System.out.println("Target is normal. Status indicator cleared.");
}
} catch (Exception e) {
System.err.println("Error during execution: " + e.getMessage());
e.printStackTrace();
}
}
 
#5 ·
Hi cljohnson3rd,

I tried using the BControlPoint method with your code but according to the API docs BControlPoint does not have a set action.
I managed to get it working with the code below using BStatusNumeric, however I am re-writing this to use BNumericPoint because if one of my points is a network point the code fails.

private void setOrdValue(String pointOrd, Double spValue) {

BOrd ordinSes = BOrd.make(pointOrd); // Create a BOrd from the pointOrd string (station:|h:22351) we are using ordInSession to prevent name changes breaking the code

OrdTarget ordTar = ordinSes.resolve(); // resolve the ordInSession to create an ordTarget

BNumericWritable bnr = (BNumericWritable) ordTar.get(); //Create a BNumericWritable with the ordTarget

BStatusValue outValue = bnr.getOutStatusValue(); //create a BStatusValue from the OutStatusValue of the BNumericWritable
try { //create a try/catch
if (outValue instanceof BStatusNumeric) { // check the BStatusValue is a BStatusNumeric
double originalValue = Double.parseDouble(bnr.getOutStatusValue().getValueValue().toString()); // get the current Double value from the BNumericWritable
if (originalValue != Double.parseDouble(spValue.toString())) { //check to see if the current value matches the new value
bnr.set(BDouble.make(spValue.toString()));
System.out.println("Setting " + bnr.toPathString() + " - TO - " + spValue);// if it doesn't then set the value of the BNumericWritable to the new value
} else if (originalValue == Double.parseDouble(spValue.toString())) {
System.out.println(bnr.toPathString() + " unchanged @ " + spValue); // if it does then print message stating both values the same
}

}
} catch (Exception ex) { // catch any exception
Exception e = ex;
if (getDebug()) { //check if debug switch is on
System.out.println("Could not update Setpoint - Exception! (" + e.getMessage() + ")"); // print the exception message
}

setErrors(true); // set the errors pin to true
}
}
 
#6 ·
Hi all,

I have modified my code to use a BNumericPoint as follows

private void setOrdValue(String pointOrd, Double spValue) {

BOrd ordinSes = BOrd.make(pointOrd); // Create a BOrd from the pointOrd string (station:|h:22351) we are using ordInSession to prevent name changes breaking the code

OrdTarget ordTar = ordinSes.resolve(); // resolve the ordInSession to create an ordTarget

BNumericPoint bnr = (BNumericPoint) ordTar.get(); //Create a BNumericWritable with the ordTarget

BStatusValue outValue = bnr.getOutStatusValue(); //create a BStatusValue from the OutStatusValue of the BNumericWritable
try { //create a try/catch
if (outValue instanceof BStatusNumeric) { // check the BStatusValue is a BStatusNumeric
double originalValue = Double.parseDouble(bnr.getOutStatusValue().getValueValue().toString()); // get the current Double value from the BNumericWritable
if (originalValue != Double.parseDouble(spValue.toString())) { //check to see if the current value matches the new value
BStatusNumeric bsn = new BStatusNumeric(spValue, BStatus.ok);
bnr.setOut(bsn);
System.out.println("Setting " + bnr.toPathString() + " - TO - " + spValue);// if it doesn't then set the value of the BNumericWritable to the new value
} else if (originalValue == Double.parseDouble(spValue.toString())) {
System.out.println(bnr.toPathString() + " unchanged @ " + spValue); // if it does then print message stating both values the same
}

}
} catch (Exception ex) { // catch any exception
Exception e = ex;
if (getDebug()) { //check if debug switch is on
System.out.println("Could not update Setpoint - Exception! (" + e.getMessage() + ")"); // print the exception message
}

setErrors(true); // set the errors pin to true
}
}

However, the line in red above is causing a Java Warning and the value is not being set, I am guessing it does not like you setting the OUT of a point directly, so my question now is how can I achieve this without creating a proxy of the point in my station?

Here is the Warning:

WARNING [08:56:20 03-Jan-25 GMT][control] ControlPoint.out set explicitly: control:NumericPoint: /Drivers/NiagaraNetwork/Hierarchy/points/sp
java.lang.Exception
at javax.baja.control.BControlPoint.fwChanged(BControlPoint.java:574)
at javax.baja.control.BControlPoint.fw(BControlPoint.java:517)
at com.tridium.sys.schema.ComponentSlotMap.fireComponentEvent(ComponentSlotMap.java:1122)
at com.tridium.sys.schema.ComponentSlotMap.modified(ComponentSlotMap.java:1005)
at com.tridium.sys.schema.ComplexSlotMap.set(ComplexSlotMap.java:1165)
at com.tridium.sys.schema.ComplexSlotMap.set(ComplexSlotMap.java:904)
at javax.baja.sys.BComplex.set(BComplex.java:849)
at javax.baja.control.BNumericPoint.setOut(BNumericPoint.java:86)
at com.sse.beOptUtil.BBeOptRec.setOrdValue(BBeOptRec.java:244)
at com.sse.beOptUtil.BBeOptRec.calculate(BBeOptRec.java:211)
at com.sse.beOptUtil.BBeOptRec.changed(BBeOptRec.java:225)
at com.tridium.sys.schema.ComponentSlotMap.fireComponentEvent(ComponentSlotMap.java:1145)
at com.tridium.sys.schema.ComponentSlotMap.modified(ComponentSlotMap.java:1005)
at com.tridium.sys.schema.ComplexSlotMap.setString(ComplexSlotMap.java:1997)
at com.tridium.sys.schema.ComplexSlotMap.setString(ComplexSlotMap.java:1882)
at javax.baja.sys.BComplex.setString(BComplex.java:867)
at javax.baja.sys.BConversionLink.propagatePropertyToProperty(BConversionLink.java:190)
at javax.baja.sys.BConversionLink.propagate(BConversionLink.java:136)
at com.tridium.sys.engine.SlotKnobs.propagate(SlotKnobs.java:61)
at com.tridium.sys.schema.ComponentSlotMap.modified(ComponentSlotMap.java:1002)
at com.tridium.sys.schema.ComplexSlotMap.modified(ComplexSlotMap.java:2200)
at com.tridium.sys.schema.ComplexSlotMap.setString(ComplexSlotMap.java:1997)
at com.tridium.sys.schema.ComplexSlotMap.setString(ComplexSlotMap.java:1882)
at javax.baja.sys.BComplex.setString(BComplex.java:867)
at com.tridium.sys.schema.ComplexSlotMap.copyFrom(ComplexSlotMap.java:361)
at javax.baja.sys.BComplex.copyFrom(BComplex.java:292)
at javax.baja.control.BControlPoint.doExecute(BControlPoint.java:309)
at auto.javax_baja_control_BStringWritable.invoke(AutoGenerated)
at com.tridium.sys.schema.ComponentSlotMap.invoke(ComponentSlotMap.java:1921)
at com.tridium.sys.engine.EngineUtil.doInvoke(EngineUtil.java:62)
at com.tridium.sys.engine.EngineManager.checkAsyncActions(EngineManager.java:471)
at com.tridium.sys.engine.EngineManager.execute(EngineManager.java:272)
at com.tridium.sys.engine.EngineManager$EngineThread.run(EngineManager.java:911)

Again, any help or pointers would be much appreciated.
 
#8 ·
I have a mixture of points, some are NumericWritable points which are local to the station, the code works perfectly with them, however when you add the ord for a point in one of the driver points folders the code fails because they are not NumericWritable, they are NumericPoint and they do not have any methods for setting them apart from setOut() but that is throwing a warning and not updating the value.

ControlPoint.out set explicitly: control:NumericPoint: /Drivers/NiagaraNetwork/Hierarchy/points/sp

Despite the API docs saying that is how you set the out of the point (as it has no in slots) and it won't accept a plain .set
 
#9 ·
So program objects can be limited to what they can do. That's just the nature. I did check a module I created and when creating the Boolean/Numeric/Enum/String points, I added additional things to them:

public BBooleanPoint generateBooleanPoint() {
BBooleanPoint bBooleanPoint = new BBooleanPoint();
bBooleanPoint.setOut(new BStatusBoolean(false, BStatus.ok));
BAlarmSourceExt bAlarmSourceExt = new BAlarmSourceExt();
bAlarmSourceExt.setOffnormalAlgorithm(new BBooleanChangeOfStateAlgorithm());
bBooleanPoint.add("alarmExt", bAlarmSourceExt);
return bBooleanPoint;
}

But it's possible that it may not work in an actual program object versus a module.
 
You have insufficient privileges to reply here.