Skip to content

Commit 65b5d3b

Browse files
committed
v0.2.4 update
add build script task to copy polished jar over to CommissioningScripts repository added support for verbose logging updated point locking logic
1 parent 19fdf18 commit 65b5d3b

File tree

6 files changed

+86
-27
lines changed

6 files changed

+86
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The *export data* button downloads all raw data as a *.json* file. The sliders a
6363

6464
## Mappings
6565

66-
Control programs with dampers should be grouped by air source. By limiting the percentage of active tests per group, we can avoid tripping the high static safety alarm on the RTU air source (for a worst case scenario, imagine all VAV dampers locked to 0% while the RTU supply fan is still pumping air into the system). If there are hot water valves, you should also consider grouping by water source. See the following tables for a list of mapping tags for this script. Also see [./resources/tags_ex1.json](./resources/tags_ex1.json) for the tag mappings I used while testing this script. Most of the time, you'll just be changing the base node in the sample expression mappings, but there may be exceptions.
66+
Control programs with dampers should be grouped by air source. By limiting the percentage of active tests per group, we can avoid tripping the high static safety alarm on the RTU air source (for a worst case scenario, imagine all VAV dampers locked to 0% while the RTU supply fan is still pumping air into the system). If there are hot water valves, you should also consider grouping by water source. See the following tables for a list of mapping tags for this script. Also see [./resources/tags_ex1.json](./resources/tags_ex1.json) for the tag mappings I used while testing this script. Most of the time, you'll just be changing the base node in the sample expression mappings, but there may be exceptions. Note: The `verbose` tag may be used to enable logging of errors that occur when setting/getting values.
6767

6868
### Sensors
6969
| Semantic Tag | Sample Expression | Description |

build.bat

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ if %ERRORLEVEL% NEQ 0 (
4444
exit
4545
)
4646
rmdir /S /Q "%classes%" >nul
47+
echo Copying to CommissioningScripts repository...
48+
copy /y "%~dp0%mainClass%.jar" "%~dp0..\commissioning-scripts\src\aces\webctrl\scripts\commissioning\fixed\%mainClass%.jar" >nul
49+
if %ERRORLEVEL% NEQ 0 (
50+
echo.
51+
echo Copy task failed.
52+
echo Press any key to exit.
53+
pause >nul
54+
exit
55+
)
4756
echo Build successful.
4857
echo Press any key to exit.
4958
pause >nul

src/aces/webctrl/scripts/terminalunits/Data.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
public class Data implements Comparable<Data> {
77
private final static DecimalFormat df = new DecimalFormat("0.#");
88
static { df.setMaximumFractionDigits(5); }
9-
private final static Pattern fanMatcher = Pattern.compile("(fan(\\d++))(?:_vfd)?_lock_flag");
10-
private final static Pattern elementMatcher = Pattern.compile("(([ech])(\\d++)(?:_(\\d++))?)_lock_flag");
11-
private final static Pattern onMatcher = Pattern.compile("(on\\d++)_lock_flag");
12-
private final static Pattern offMatcher = Pattern.compile("(off\\d++)_lock_flag");
9+
private final static Pattern fanMatcher = Pattern.compile("(fan(\\d++))(?:_vfd)?_lock_value");
10+
private final static Pattern elementMatcher = Pattern.compile("(([ech])(\\d++)(?:_(\\d++))?)_lock_value");
11+
private final static Pattern onMatcher = Pattern.compile("(on\\d++)_lock_value");
12+
private final static Pattern offMatcher = Pattern.compile("(off\\d++)_lock_value");
1313
public volatile ResolvedTestingUnit x;
1414
public volatile Params p;
1515
public volatile int group;
@@ -25,10 +25,11 @@ public class Data implements Comparable<Data> {
2525
private volatile OATemp oat;
2626
private volatile OADamper oad;
2727
private volatile Airflow air;
28-
private volatile Fan fans[];
28+
private volatile Fan[] fans;
2929
private volatile boolean hasFans = false;
30-
private volatile Element elements[];
30+
private volatile Element[] elements;
3131
private volatile int numElements = 0;
32+
private volatile Output[] onOffLocks;
3233
private volatile boolean dehumStartTest = false;
3334
private volatile boolean dehumStopTest = false;
3435
private volatile boolean alarmTriggered = false;
@@ -47,6 +48,7 @@ public Data(ResolvedTestingUnit x, Params p) throws Throwable {
4748
group = x.getGroup();
4849
path = x.getDisplayPath();
4950
link = x.getPersistentLink();
51+
x.verbose = Component.parseBoolean(x.getValue("verbose"));
5052
try{
5153
final String s = x.getValue("timeout_multiplier");
5254
if (s!=null){
@@ -76,18 +78,22 @@ public Data(ResolvedTestingUnit x, Params p) throws Throwable {
7678
if (!air.isDefined()){ air = null; }
7779
{
7880
Set<String> tags = x.getTags();
79-
int n = 0, m = 0;
81+
int n = 0, m = 0, k = 0;
8082
for (String s:tags){
8183
if (fanMatcher.matcher(s).matches()){
8284
++n;
8385
}else if (elementMatcher.matcher(s).matches()){
8486
++m;
87+
}else if (ctrl && (onMatcher.matcher(s).matches() || offMatcher.matcher(s).matches())){
88+
++k;
8589
}
8690
}
8791
fans = new Fan[n];
8892
elements = new Element[m];
93+
onOffLocks = new Output[k];
8994
n = 0;
9095
m = 0;
96+
k = 0;
9197
String ss;
9298
Matcher mm;
9399
for (String s:tags){
@@ -115,9 +121,13 @@ public Data(ResolvedTestingUnit x, Params p) throws Throwable {
115121
}
116122
}else if (ctrl){
117123
if ((mm=onMatcher.matcher(s)).matches()){
118-
new Output(this, mm.group(1)).set(true);
124+
onOffLocks[k] = new Output(this, mm.group(1));
125+
onOffLocks[k].set(true);
126+
++k;
119127
}else if ((mm=offMatcher.matcher(s)).matches()){
120-
new Output(this, mm.group(1)).set(false);
128+
onOffLocks[k] = new Output(this, mm.group(1));
129+
onOffLocks[k].set(false);
130+
++k;
121131
}
122132
}
123133
}
@@ -639,6 +649,9 @@ public void print(final StringBuilder sb, final boolean JSON){
639649
prefix|=addProblem(sb, elements[i], elements[i].ID, prefix);
640650
}
641651
}
652+
for (i=0;i<onOffLocks.length;++i){
653+
prefix|=addProblem(sb, onOffLocks[i], onOffLocks[i].getPrefix(), prefix);
654+
}
642655
sb.append("\n],\n");
643656
prefix = false;
644657
sb.append("\"faults\":[\n");
@@ -667,6 +680,9 @@ public void print(final StringBuilder sb, final boolean JSON){
667680
prefix|=addFault(sb, elements[i], elements[i].ID, prefix);
668681
}
669682
}
683+
for (i=0;i<onOffLocks.length;++i){
684+
prefix|=addFault(sb, onOffLocks[i], onOffLocks[i].getPrefix(), prefix);
685+
}
670686
sb.append("\n]");
671687
if (tempTrend!=null){
672688
prefix = false;

src/aces/webctrl/scripts/terminalunits/Output.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@
222222
table.appendChild(tbody);
223223
const trTitle = document.createElement("TR");
224224
const trHeaders = document.createElement("TR");
225+
thead.style.position = "sticky";
226+
thead.style.top = "0";
225227
thead.appendChild(trTitle);
226228
thead.appendChild(trHeaders);
227229
const tdTitle = document.createElement("TD");
@@ -389,13 +391,13 @@
389391
addTest("Actual Airflow\n"+airMax.toFixed(0)+" cfm\nAttained Cooling Max\n"+airCoolMax+" cfm", airMax*100>=airCoolMax*(100-Number(damperMargin.value)), tdGeneralTests, tr.filters, "AirflowMax");
390392
addTest("No Airflow When Damper Closed", Math.abs(airData[0])<margin, tdGeneralTests, tr.filters, "AirflowClosed");
391393
let inc = true;
392-
let prev = airData[0];
394+
let max = airData[0];
393395
for (const cur of airData) {
394-
if (prev > cur + margin) {
396+
if (max > cur + margin) {
395397
inc = false;
396398
break;
397399
}
398-
prev = cur;
400+
max = Math.max(cur, max);
399401
}
400402
addTest("Airflow Increasing With Damper Position", inc, tdGeneralTests, tr.filters, "AirflowIncrease");
401403
}
@@ -782,6 +784,7 @@ <h3>Filters</h3>
782784
testsCompletedBar.style.width = String(ret["completed"]) + '%';
783785
}
784786
reloadData();
787+
applyFilters();
785788
} catch (e) {
786789
console.error(e);
787790
}

src/aces/webctrl/scripts/terminalunits/Output.java

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,31 @@ public class Output extends Component {
99
private volatile String lock_max = "_lock_max";
1010
private volatile String fault = "_fault";
1111
private volatile boolean hasLock = false;
12+
private volatile boolean hasLockFlag = false;
1213
private volatile boolean hasBounds = false;
1314
private volatile boolean hasFault = false;
1415
private volatile double min = 0;
1516
private volatile double max = 100;
1617
private volatile boolean literal = false;
1718
private volatile boolean locked = false;
19+
private volatile String prefix = null;
1820
public Output(Data d, String prefix) throws InterruptedException {
1921
super(d);
22+
this.prefix = prefix;
2023
lock_flag = prefix+lock_flag;
2124
lock_value = prefix+lock_value;
2225
lock_min = prefix+lock_min;
2326
lock_max = prefix+lock_max;
2427
fault = prefix+fault;
25-
hasLock = d.x.hasMapping(lock_flag) && d.x.hasMapping(lock_value);
28+
hasLock = d.x.hasMapping(lock_value);
29+
hasLockFlag = d.x.hasMapping(lock_flag);
2630
if (hasLock){
27-
String s = d.x.getValue(lock_flag);
28-
if (s==null){ problem = true; }
29-
locked = parseBoolean(s);
31+
String s;
32+
if (hasLockFlag){
33+
s = d.x.getValue(lock_flag);
34+
if (s==null){ problem = true; }
35+
locked = parseBoolean(s);
36+
}
3037
hasFault = d.x.hasMapping(fault);
3138
hasBounds = d.x.hasMapping(lock_min) && d.x.hasMapping(lock_max);
3239
if (hasBounds){
@@ -41,7 +48,9 @@ public Output(Data d, String prefix) throws InterruptedException {
4148
s = null;
4249
if (x==null || y==null){
4350
problem = true;
44-
}else if (x!=y){
51+
}else if (x.equals(y)){
52+
literal = true;
53+
}else{
4554
min = Math.min(x,y);
4655
max = Math.max(x,y);
4756
}
@@ -56,11 +65,15 @@ public Output(Data d, String prefix, double min, double max) throws InterruptedE
5665
lock_min = prefix+lock_min;
5766
lock_max = prefix+lock_max;
5867
fault = prefix+fault;
59-
hasLock = d.x.hasMapping(lock_flag) && d.x.hasMapping(lock_value);
68+
hasLock = d.x.hasMapping(lock_value);
69+
hasLockFlag = d.x.hasMapping(lock_flag);
6070
if (hasLock){
61-
String s = d.x.getValue(lock_flag);
62-
if (s==null){ problem = true; }
63-
locked = parseBoolean(s);
71+
String s;
72+
if (hasLockFlag){
73+
s = d.x.getValue(lock_flag);
74+
if (s==null){ problem = true; }
75+
locked = parseBoolean(s);
76+
}
6477
hasFault = d.x.hasMapping(fault);
6578
hasBounds = true;
6679
this.min = min;
@@ -75,7 +88,11 @@ public Output(Data d, String prefix, double min, double max) throws InterruptedE
7588
* @return whether the lock was released successfully.
7689
*/
7790
public boolean unlock() throws InterruptedException {
78-
if (locked && hasLock){
91+
if (!hasLockFlag){
92+
locked = false;
93+
return true;
94+
}
95+
if (locked){
7996
if (d.x.setValueAutoMark(lock_flag, false)){
8097
locked = false;
8198
}else{
@@ -89,7 +106,11 @@ public boolean unlock() throws InterruptedException {
89106
* @return whether the lock was acquired successfully.
90107
*/
91108
public boolean lock() throws InterruptedException {
92-
if (!locked && hasLock){
109+
if (!hasLockFlag){
110+
locked = true;
111+
return true;
112+
}
113+
if (!locked){
93114
if (d.x.setValueAutoMark(lock_flag, true)){
94115
locked = true;
95116
}else{
@@ -98,6 +119,10 @@ public boolean lock() throws InterruptedException {
98119
}
99120
return locked;
100121
}
122+
private static String doubleToSafeString(double x){
123+
final String s = String.valueOf(x);
124+
return s.endsWith(".0")?s.substring(0,s.length()-2):s;
125+
}
101126
/**
102127
* Sets the value of this output. If necessary, a lock is acquired on this output.
103128
* @return whether the output was set successfully.
@@ -106,7 +131,7 @@ public boolean set(boolean value) throws InterruptedException {
106131
if (!hasLock){
107132
return false;
108133
}
109-
if (d.x.setValueAutoMark(lock_value, hasBounds?(value?max:min):(value?"1":"0"))){
134+
if (d.x.setValueAutoMark(lock_value, literal?value:(hasBounds?doubleToSafeString(value?max:min):(value?"1":"0")))){
110135
if (lock()){
111136
return true;
112137
}
@@ -124,7 +149,7 @@ public boolean set(double value) throws InterruptedException {
124149
if (!hasLock){
125150
return false;
126151
}
127-
if (d.x.setValueAutoMark(lock_value, literal?value:(hasBounds?min+value*(max-min):(value>=0.5?"1":"0")))){
152+
if (d.x.setValueAutoMark(lock_value, literal?value:(hasBounds?doubleToSafeString(min+value*(max-min)):(value>=0.5?"1":"0")))){
128153
if (lock()){
129154
return true;
130155
}
@@ -159,4 +184,10 @@ public boolean isAnalog(){
159184
}
160185
return false;
161186
}
187+
/**
188+
* @return the tag prefix used to construct this output.
189+
*/
190+
public String getPrefix(){
191+
return prefix;
192+
}
162193
}

src/aces/webctrl/scripts/terminalunits/TerminalUnitTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class TerminalUnitTest extends Script {
1111
private volatile String outputString = null;
1212
private volatile Params p = null;
1313
@Override public String getDescription(){
14-
return "<a href=\"https://github.com/automatic-controls/terminal-unit-script\" target=\"_blank\" style=\"border:none;\">Terminal Unit Commissioning Script</a> v0.2.3<br>Evaluates performance of fans, dampers, heating, cooling, and dehumidification components.";
14+
return "<a href=\"https://github.com/automatic-controls/terminal-unit-script\" target=\"_blank\" style=\"border:none;\">Terminal Unit Commissioning Script</a> v0.2.4<br>Evaluates performance of fans, dampers, heating, cooling, and dehumidification components.";
1515
}
1616
@Override public String[] getParamNames(){
1717
return new String[]{"Dampers", "Fans", "Heating / Cooling"};

0 commit comments

Comments
 (0)