diff --git a/DEPENDENCIES b/DEPENDENCIES index ebc7151..d6e6835 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,3 +1,3 @@ file:tomcat-embed-core:webserver\lib -url:CommissioningScripts-0.1.1.jar:https://github.com/automatic-controls/commissioning-scripts/releases/download/v0.1.1-beta/CommissioningScripts-0.1.1.jar -url:CommissioningScripts-0.1.1-sources.jar:https://github.com/automatic-controls/commissioning-scripts/releases/download/v0.1.1-beta/CommissioningScripts-0.1.1-sources.jar \ No newline at end of file +url:CommissioningScripts-0.1.2.jar:https://github.com/automatic-controls/commissioning-scripts/releases/download/v0.1.2-beta/CommissioningScripts-0.1.2.jar +url:CommissioningScripts-0.1.2-sources.jar:https://github.com/automatic-controls/commissioning-scripts/releases/download/v0.1.2-beta/CommissioningScripts-0.1.2-sources.jar \ No newline at end of file diff --git a/README.md b/README.md index 68d0fb0..7ca03f6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Terminal Unit Commissioning Script v0.1.0 +# Terminal Unit Commissioning Script WebCTRL is a trademark of Automated Logic Corporation. Any other trademarks mentioned herein are the property of their respective owners. -- [Terminal Unit Commissioning Script v0.1.0](#terminal-unit-commissioning-script-v010) +- [Terminal Unit Commissioning Script](#terminal-unit-commissioning-script) - [Overview](#overview) - [High-Level Pseudocode](#high-level-pseudocode) - [Supply Fan, Damper, and Hot Water Valve](#supply-fan-damper-and-hot-water-valve) diff --git a/build.bat b/build.bat index ecebe60..494b516 100644 --- a/build.bat +++ b/build.bat @@ -5,7 +5,7 @@ echo. :: Modify these parameters when necessary set "WebCTRL=C:\WebCTRL8.0" set "mainClass=TerminalUnitTest" -set "package=" +set "package=aces\webctrl\scripts\terminalunits\" set "jdk=%JAVA_HOME%\bin" set "release=8" @@ -34,7 +34,7 @@ if %ERRORLEVEL% NEQ 0 ( echo Packing... robocopy /E "%~dp0src" "%classes%" /XF "*.java" >nul 2>nul if exist "%~dp0%mainClass%.jar" del /F "%~dp0%mainClass%.jar" >nul 2>nul -"%jdk%\jar.exe" --create --verbose --file "%~dp0%mainClass%.jar" --main-class "%package%%mainClass%" -C "%classes%" . >nul +"%jdk%\jar.exe" --create --verbose --file "%~dp0%mainClass%.jar" --main-class "%package:\=.%%mainClass%" -C "%classes%" . >nul if %ERRORLEVEL% NEQ 0 ( rmdir /S /Q "%classes%" >nul echo. diff --git a/src/TerminalUnitTest.java b/src/TerminalUnitTest.java deleted file mode 100644 index 881a56f..0000000 --- a/src/TerminalUnitTest.java +++ /dev/null @@ -1,1220 +0,0 @@ -import aces.webctrl.scripts.commissioning.core.*; -import aces.webctrl.scripts.commissioning.web.*; -import javax.servlet.http.*; -import java.util.*; -import java.util.function.*; -import java.util.concurrent.atomic.*; -public class TerminalUnitTest extends Script { - private volatile boolean exited = false; - private volatile Data[] data; - private final AtomicInteger index = new AtomicInteger(); - private volatile boolean testDampers = false; - private volatile boolean testFans = false; - private volatile boolean testHeating = false; - private volatile boolean initialized = false; - @Override public String getDescription(){ - return "Terminal Unit Commissioning Script v0.1.0
Evaluates performance of fans, dampers, and heating components."; - } - @Override public String[] getParamNames(){ - return new String[]{"Dampers", "Fans", "Heating"}; - } - @Override public void exit(){ - exited = true; - } - @Override public void init(){ - data = new Data[this.testsTotal]; - Arrays.fill(data,null); - testDampers = this.params.getOrDefault("Dampers",false); - testFans = this.params.getOrDefault("Fans",false); - testHeating = this.params.getOrDefault("Heating",false); - initialized = true; - } - @Override public void exec(ResolvedTestingUnit x) throws Throwable { - final int index = this.index.getAndIncrement(); - if (index>=data.length){ - Initializer.log(new ArrayIndexOutOfBoundsException("Index exceeded expected capacity: "+index+">="+data.length)); - return; - } - data[index] = new Data(x); - } - @Override public String getOutput(boolean email) throws Throwable { - if (!initialized){ - return null; - } - final StringBuilder sb = new StringBuilder(8192); - sb.append("\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("Terminal Unit Report\n"); - if (email){ - sb.append("\n"); - }else{ - sb.append("\n"); - } - sb.append("\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("

Terminal Unit Report

\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("Export Data\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append("\n"); - sb.append("\n"); - sb.append("
\n"); - if (!exited){ - sb.append("

\n"); - sb.append("
\n"); - sb.append("
\n"); - sb.append(Utility.format("
\n", 100*this.testsStarted.get()/this.testsTotal)); - sb.append(Utility.format("
\n", 100*this.testsCompleted.get()/this.testsTotal)); - sb.append("
\n"); - sb.append("
\n"); - }else if (this.test.isKilled()){ - sb.append("

Foribly Terminated Before Natural Completion

\n"); - }else{ - sb.append("
\n"); - } - sb.append("
\n"); - sb.append("

\n"); - sb.append("\n"); - sb.append("\n"); - sb.append(""); - return sb.toString(); - } - @Override public void updateAJAX(HttpServletRequest req, HttpServletResponse res) throws Throwable { - res.setContentType("text/plain"); - final StringBuilder sb = new StringBuilder(4096); - sb.append(Utility.format("{\"started\":$0,\"completed\":$1,\"data\":", 100*this.testsStarted.get()/this.testsTotal, 100*this.testsCompleted.get()/this.testsTotal)); - printData(sb,true); - sb.append('}'); - res.getWriter().print(ExpansionUtils.expandLinks(sb.toString(),req)); - } - private void printData(final StringBuilder sb, final boolean JSON){ - final ArrayList list = new ArrayList(data.length); - { - Data d; - for (int i=0;i { - private final static String tagAirflow = "airflow"; - private final static String tagAirflowMaxHeat = "airflow_max_heat"; - private final static String tagAirflowMaxCool = "airflow_max_cool"; - private final static String tagAirflowLockFlag = "airflow_lock_flag"; - private final static String tagAirflowLockValue = "airflow_lock_value"; - private final static String tagDamperLockFlag = "damper_lock_flag"; - private final static String tagDamperLockValue = "damper_lock_value"; - private final static String tagDamperPosition = "damper_position"; - private final static String tagEAT = "eat"; - private final static String tagLAT = "lat"; - private final static String tagSFSSLockFlag = "sfss_lock_flag"; - private final static String tagSFSSLockValue = "sfss_lock_value"; - private final static String tagSFST = "sfst"; - private final static String tagHeatAOLockFlag = "heating_AO_lock_flag"; - private final static String tagHeatAOLockValue = "heating_AO_lock_value"; - private final static String tagHeatAOPosition = "heating_AO_position"; - private final static String tagPumpStatus = "pump_status"; - private final static String tagPumpCmdLockFlag = "pump_cmd_lock_flag"; - private final static String tagPumpCmdLockValue = "pump_cmd_lock_value"; - private final static String tagPumpRevLockFlag = "pump_rev_lock_flag"; - private final static String tagPumpRevLockValue = "pump_rev_lock_value"; - private final static double lowLimit = 40.0; - private final static double highLimit = 120.0; - public volatile ResolvedTestingUnit x; - public volatile int group; - public volatile String path; - public volatile String link; - public volatile long start = -1; - public volatile long end = -1; - public volatile boolean hasFan; - public volatile boolean hasDamper; - public volatile boolean hasHeatAO; - public volatile boolean hasEAT; - public volatile boolean hasPump; - public volatile boolean fanError = false; - public volatile boolean fanStopTest = false; - public volatile boolean fanStartTest = false; - public volatile boolean damperError = false; - public volatile boolean damperResponse = true; - public volatile Stats[] airflowY; - private final static int airflowSamples = 5; - public volatile double airflowMaxCoolValue = 0; - public volatile double airflowMaxHeatValue = 0; - public volatile boolean heatingError = false; - public volatile boolean heatingFailure = false; - public volatile String heatingFailMsg = "Failure"; - public volatile double[] heatingX; - public volatile double[] heatingY; - public volatile int heatingSamples; - public Data(ResolvedTestingUnit x) throws Throwable { - start = System.currentTimeMillis(); - this.x = x; - group = x.getGroup(); - path = x.getDisplayPath(); - link = x.getPersistentLink(); - Boolean b; - String s=null,t=null; - Stats st; - String airflowMaxHeat = null; - String airflowMaxCool = null; - hasFan = x.hasMapping(tagSFSSLockFlag) - && x.hasMapping(tagSFSSLockValue) - && x.hasMapping(tagSFST); - hasDamper = x.hasMapping(tagAirflow) - && x.hasMapping(tagAirflowLockFlag) - && x.hasMapping(tagAirflowLockValue) - && x.hasMapping(tagAirflowMaxCool) - && x.hasMapping(tagAirflowMaxHeat) - && x.hasMapping(tagDamperLockFlag) - && x.hasMapping(tagDamperLockValue) - && x.hasMapping(tagDamperPosition); - hasHeatAO = x.hasMapping(tagHeatAOLockFlag) - && x.hasMapping(tagHeatAOLockValue) - && x.hasMapping(tagHeatAOPosition) - && x.hasMapping(tagLAT); - hasPump = x.hasMapping(tagPumpCmdLockFlag) - && x.hasMapping(tagPumpCmdLockValue) - && x.hasMapping(tagPumpRevLockFlag) - && x.hasMapping(tagPumpRevLockValue) - && x.hasMapping(tagPumpStatus) - && x.hasMapping(tagLAT); - hasEAT = x.hasMapping(tagEAT); - if (hasFan && testFans || hasDamper && testDampers){ - // If we're going to test fans or dampers, first we make an attempt to shut-off all heating and cooling elements - if (hasHeatAO){ - x.setValueAutoMark(tagHeatAOLockValue,0); - x.setValueAutoMark(tagHeatAOLockFlag,true); - } - if (hasPump){ - x.setValueAutoMark(tagPumpCmdLockValue,0); - x.setValueAutoMark(tagPumpCmdLockFlag,true); - } - if (hasHeatAO){ - Thread.sleep(30000); - } - if (hasPump){ - waitFor(180000, 3000, tagPumpStatus, new Predicate(){ - public boolean test(String s){ - return s.equals("0"); - } - }); - } - } - if (hasFan && testFans) fanTest: { - // Test the fan by locking it off and then on - if (!x.setValueAutoMark(tagSFSSLockValue, 0) || !x.setValueAutoMark(tagSFSSLockFlag, true)){ - fanError = true; break fanTest; - } - b = waitFor(180000, 3000, tagSFST, new Predicate(){ - public boolean test(String s){ - return s.equals("0"); - } - }); - if (b==null){ - fanError = true; break fanTest; - } - fanStopTest = b; - if (!x.setValueAutoMark(tagSFSSLockValue, 1)){ - fanError = true; break fanTest; - } - b = waitFor(180000, 3000, tagSFST, new Predicate(){ - public boolean test(String s){ - return s.equals("1"); - } - }); - if (b==null){ - fanError = true; break fanTest; - } - fanStartTest = b; - } else if (hasFan && (hasDamper && testDampers || hasHeatAO && testHeating || hasPump && testHeating)){ - // If we're going to test dampers or heating/cooling elements, then we lock the fan on - if (x.setValueAutoMark(tagSFSSLockValue, 1) && x.setValueAutoMark(tagSFSSLockFlag, true)){ - b = waitFor(180000, 3000, tagSFST, new Predicate(){ - public boolean test(String s){ - return s.equals("1"); - } - }); - if (b!=null && b){ - fanStartTest = true; - } - } - } - if (hasDamper && testDampers) damperTest: { - // Test the damper by locking it to 0%, and then measuring the airflow at 5% increment intervals - try{ - if (airflowMaxCool==null && (airflowMaxCool=x.getValue(tagAirflowMaxCool))==null){ - damperError = true; break damperTest; - } - airflowMaxCoolValue = Double.parseDouble(airflowMaxCool); - airflowY = new Stats[airflowX.length]; - for (int i=0;i(){ - public boolean test(String s){ - return Math.abs(Double.parseDouble(s)-pos)<1; - } - }); - if (b==null){ - damperError = true; break damperTest; - }else if (!b){ - damperResponse = false; break damperTest; - } - if ((st = evaluate(airflowSamples, 2000, tagAirflow))==null){ - damperError = true; break damperTest; - } - airflowY[i] = st; - } - }catch(NumberFormatException e){ - Initializer.log(e); - damperError = true; - } - } - if (hasHeatAO && testHeating) heatTest: { - // Test heating AO by locking to 0%, waiting for stabilization, locking to 100%, and measuring the temperature at 10 second intervals - // If a damper exists, we lock it to the heating maximum airflow parameter - // We ensure there is sufficient airflow at every interval of the test (e.g, to prevent fires / overheating) - try{ - if (!fanStartTest && !hasDamper){ - heatingFailure = true; - heatingFailMsg = "Loss of Airflow"; - break heatTest; - } - if ((s=x.getValue(tagHeatAOPosition))==null){ - heatingError = true; break heatTest; - } - final double initialPosition = Double.parseDouble(s); - if (!x.setValueAutoMark(tagHeatAOLockValue,0) || !x.setValueAutoMark(tagHeatAOLockFlag,true)){ - heatingError = true; break heatTest; - } - if (hasDamper){ - final long lim = System.currentTimeMillis()+30000L+(long)(initialPosition*6000); - if (airflowMaxHeat==null && (airflowMaxHeat=x.getValue(tagAirflowMaxHeat))==null){ - heatingError = true; break heatTest; - } - airflowMaxHeatValue = Math.max(Double.parseDouble(airflowMaxHeat),150); - if (!x.setValueAutoMark(tagAirflowLockValue, airflowMaxHeatValue) || !x.setValueAutoMark(tagDamperLockFlag, false) || !x.setValueAutoMark(tagAirflowLockFlag, true)){ - heatingError = true; break heatTest; - } - waitFor(240000, 3000, tagAirflow, new Predicate(){ - public boolean test(String s){ - return Math.abs(Double.parseDouble(s)-airflowMaxHeatValue)<50; - } - }); - final long dif = lim-System.currentTimeMillis(); - if (dif>0){ - Thread.sleep(dif); - } - }else{ - Thread.sleep(30000L+(long)(initialPosition*6000)); - } - s = "0"; - if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ - heatingError = true; break heatTest; - } - final long startTime = System.currentTimeMillis(); - heatingX = new double[61]; - heatingY = new double[heatingX.length]; - heatingSamples = heatingX.length; - heatingX[0] = 0; - heatingY[0] = Double.parseDouble(t)-Double.parseDouble(s); - if (!x.setValueAutoMark(tagHeatAOLockValue,100)){ - heatingError = true; break heatTest; - } - double yMax = 0; - double yAvg = 0; - double lat = 0; - long time = 0; - for (int i=1,j;ihighLimit){ - heatingSamples = i+1; - break; - } - if (heatingY[i]>yMax){ - yMax = heatingY[i]; - } - if (i>21){ - yAvg = 0; - for (j=0;j<8;++j){ - yAvg+=heatingY[i-j-3]; - } - yAvg/=8; - if (yAvg+yMax/50>(heatingY[i]+heatingY[i-1]+heatingY[i-2])/3){ - heatingSamples = i+1; - break; - } - } - } - heatingY[0] = 0; - }catch(NumberFormatException e){ - Initializer.log(e); - heatingError = true; - }finally{ - x.setValueAutoMark(tagHeatAOLockValue,0); - } - } - if (hasPump && testHeating && !hasHeatAO) heatTest: { - try{ - if (!fanStartTest && !hasDamper){ - heatingFailure = true; - heatingFailMsg = "Loss of Airflow"; - break heatTest; - } - if (!x.setValueAutoMark(tagPumpRevLockValue,0) || !x.setValueAutoMark(tagPumpRevLockFlag,true) || !x.setValueAutoMark(tagPumpCmdLockValue,0) || !x.setValueAutoMark(tagPumpCmdLockFlag,true)){ - heatingError = true; break heatTest; - } - b = waitFor(180000, 3000, tagPumpStatus, new Predicate(){ - public boolean test(String s){ - return s.equals("0"); - } - }); - if (b==null){ - heatingError = true; break heatTest; - }else if (!b){ - heatingFailure = true; - heatingFailMsg = "Compressor Stop Failure"; - break heatTest; - } - Thread.sleep(480000L); - s = "0"; - heatingX = new double[181]; - heatingY = new double[heatingX.length]; - heatingSamples = heatingX.length; - heatingX[0] = 0; - heatingY[0] = 0; - for (int i=0;i<4;++i){ - Thread.sleep(3000); - if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ - heatingError = true; break heatTest; - } - heatingY[0]+=Double.parseDouble(t)-Double.parseDouble(s); - } - heatingY[0]/=4; - final long startTime = System.currentTimeMillis(); - if (!x.setValueAutoMark(tagPumpCmdLockValue,1)){ - heatingError = true; break heatTest; - } - String u = ""; - int pumpStart = -1; - int swap = -1; - boolean swapped = false; - boolean firstCooling = true; - double yMax=0; - double yMin=0; - double sum=0; - double yAvg=0; - double yAvg2=0; - long time = 0; - double lat = 0; - for (int i=1,j;i>1)-5; - }else if (i>18){ - heatingFailure = true; - heatingFailMsg = "Compressor Start Failure"; - break heatTest; - } - } - if (!swapped && i>=swap && swap!=-1){ - swapped = true; - swap = i+30; - firstCooling = sum<=0; - if (!x.setValueAutoMark(tagPumpRevLockValue,1)){ - heatingError = true; break heatTest; - } - } - time = System.currentTimeMillis(); - if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ - heatingError = true; break heatTest; - }else if ((b=checkAirflow())==null){ - heatingError = true; break heatTest; - }else if (!b){ - heatingFailure = true; - heatingFailMsg = "Loss of Airflow"; - break heatTest; - } - lat = Double.parseDouble(t); - heatingX[i] = (time-startTime)/60000.0; - heatingY[i] = lat-Double.parseDouble(s)-heatingY[0]; - if (pumpStart!=-1 && (lat>highLimit || latyMax){ - yMax = heatingY[i]; - } - if (heatingY[i]pumpStart && pumpStart!=-1 || swapped && i>swap){ - yAvg = 0; - for (j=0;j<10;++j){ - yAvg+=heatingY[i-j-5]; - } - yAvg/=10; - yAvg2 = (heatingY[i]+heatingY[i-1]+heatingY[i-2]+heatingY[i-3]+heatingY[i-4])/5; - if (swapped){ - if (firstCooling && yAvg+yMax/50>yAvg2 || !firstCooling && yAvg+yMin/500 && yAvg+yMax/50>yAvg2 || sum<=0 && yAvg+yMin/5090){ - return true; - } - } - Thread.sleep(2000); - } - } - return false; - } - private Boolean waitFor(long timeout, long interval, String tag, Predicate test) throws Throwable { - final long lim = System.currentTimeMillis()+timeout; - String s; - do { - if ((s=x.getValue(tag))==null){ - return null; - } - if (test.test(s)){ - return true; - } - if (System.currentTimeMillis()>=lim){ - break; - } - Thread.sleep(interval); - } while (System.currentTimeMillis() + + + Terminal Unit Report + __CSS__ + + + + +
+

Terminal Unit Report

+ + + Export Data +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ __PROGRESS_BAR__ +
+

+ + + \ No newline at end of file diff --git a/src/Stats.java b/src/aces/webctrl/scripts/terminalunits/Stats.java similarity index 91% rename from src/Stats.java rename to src/aces/webctrl/scripts/terminalunits/Stats.java index 5284191..80a86ec 100644 --- a/src/Stats.java +++ b/src/aces/webctrl/scripts/terminalunits/Stats.java @@ -1,3 +1,4 @@ +package aces.webctrl.scripts.terminalunits; public class Stats { public volatile double[] arr; public volatile double mean = 0; diff --git a/src/aces/webctrl/scripts/terminalunits/TerminalUnitTest.java b/src/aces/webctrl/scripts/terminalunits/TerminalUnitTest.java new file mode 100644 index 0000000..d19bf55 --- /dev/null +++ b/src/aces/webctrl/scripts/terminalunits/TerminalUnitTest.java @@ -0,0 +1,732 @@ +package aces.webctrl.scripts.terminalunits; +import aces.webctrl.scripts.commissioning.core.*; +import aces.webctrl.scripts.commissioning.web.*; +import javax.servlet.http.*; +import java.util.*; +import java.util.function.*; +import java.util.concurrent.atomic.*; +public class TerminalUnitTest extends Script { + private volatile boolean exited = false; + private volatile Data[] data; + private final AtomicInteger index = new AtomicInteger(); + private volatile boolean testDampers = false; + private volatile boolean testFans = false; + private volatile boolean testHeating = false; + private volatile boolean initialized = false; + private volatile String outputString = null; + @Override public String getDescription(){ + return "Terminal Unit Commissioning Script v0.1.0
Evaluates performance of fans, dampers, and heating components."; + } + @Override public String[] getParamNames(){ + return new String[]{"Dampers", "Fans", "Heating"}; + } + @Override public void exit(){ + exited = true; + } + @Override public void init() throws Throwable { + data = new Data[this.testsTotal]; + Arrays.fill(data,null); + testDampers = this.params.getOrDefault("Dampers",false); + testFans = this.params.getOrDefault("Fans",false); + testHeating = this.params.getOrDefault("Heating",false); + outputString = Utility.loadResourceAsString(TerminalUnitTest.class.getClassLoader(), "aces/webctrl/scripts/terminalunits/Output.html"); + initialized = true; + } + @Override public void exec(ResolvedTestingUnit x) throws Throwable { + final int index = this.index.getAndIncrement(); + if (index>=data.length){ + Initializer.log(new ArrayIndexOutOfBoundsException("Index exceeded expected capacity: "+index+">="+data.length)); + return; + } + data[index] = new Data(x); + } + @Override public String getOutput(boolean email) throws Throwable { + if (!initialized){ + return null; + } + final boolean notExited = !exited; + return outputString.replace( + "__TEST_FANS__", + String.valueOf(testFans) + ).replace( + "__TEST_DAMPERS__", + String.valueOf(testDampers) + ).replace( + "__TEST_HEATING__", + String.valueOf(testHeating) + ).replace( + "__NOT_EXITED__", + String.valueOf(notExited) + ).replace( + "__PROGRESS_BAR__", + notExited ? ( + "

\n"+ + "
\n"+ + "
\n"+ + Utility.format("
\n", 100*this.testsStarted.get()/this.testsTotal)+ + Utility.format("
\n", 100*this.testsCompleted.get()/this.testsTotal)+ + "
\n"+ + "
" + ):( + this.test.isKilled() ? ( + "

Foribly Terminated Before Natural Completion

" + ):( + "
" + ) + ) + ).replace( + "__CSS__", + email ? ( + "" + ):( + "" + ) + ).replace( + "__DATA__", + printData(null,false).toString() + ); + } + @Override public void updateAJAX(HttpServletRequest req, HttpServletResponse res) throws Throwable { + res.setContentType("text/plain"); + final StringBuilder sb = new StringBuilder(4096); + sb.append(Utility.format("{\"started\":$0,\"completed\":$1,\"data\":", 100*this.testsStarted.get()/this.testsTotal, 100*this.testsCompleted.get()/this.testsTotal)); + printData(sb,true); + sb.append('}'); + res.getWriter().print(ExpansionUtils.expandLinks(sb.toString(),req)); + } + private StringBuilder printData(StringBuilder sb, final boolean JSON){ + final ArrayList list = new ArrayList(data.length); + { + Data d; + for (int i=0;i { + private final static String tagAirflow = "airflow"; + private final static String tagAirflowMaxHeat = "airflow_max_heat"; + private final static String tagAirflowMaxCool = "airflow_max_cool"; + private final static String tagAirflowLockFlag = "airflow_lock_flag"; + private final static String tagAirflowLockValue = "airflow_lock_value"; + private final static String tagDamperLockFlag = "damper_lock_flag"; + private final static String tagDamperLockValue = "damper_lock_value"; + private final static String tagDamperPosition = "damper_position"; + private final static String tagEAT = "eat"; + private final static String tagLAT = "lat"; + private final static String tagSFSSLockFlag = "sfss_lock_flag"; + private final static String tagSFSSLockValue = "sfss_lock_value"; + private final static String tagSFST = "sfst"; + private final static String tagHeatAOLockFlag = "heating_AO_lock_flag"; + private final static String tagHeatAOLockValue = "heating_AO_lock_value"; + private final static String tagHeatAOPosition = "heating_AO_position"; + private final static String tagPumpStatus = "pump_status"; + private final static String tagPumpCmdLockFlag = "pump_cmd_lock_flag"; + private final static String tagPumpCmdLockValue = "pump_cmd_lock_value"; + private final static String tagPumpRevLockFlag = "pump_rev_lock_flag"; + private final static String tagPumpRevLockValue = "pump_rev_lock_value"; + private final static double lowLimit = 40.0; + private final static double highLimit = 120.0; + public volatile ResolvedTestingUnit x; + public volatile int group; + public volatile String path; + public volatile String link; + public volatile long start = -1; + public volatile long end = -1; + public volatile boolean hasFan; + public volatile boolean hasDamper; + public volatile boolean hasHeatAO; + public volatile boolean hasEAT; + public volatile boolean hasPump; + public volatile boolean fanError = false; + public volatile boolean fanStopTest = false; + public volatile boolean fanStartTest = false; + public volatile boolean damperError = false; + public volatile boolean damperResponse = true; + public volatile Stats[] airflowY; + private final static int airflowSamples = 5; + public volatile double airflowMaxCoolValue = 0; + public volatile double airflowMaxHeatValue = 0; + public volatile boolean heatingError = false; + public volatile boolean heatingFailure = false; + public volatile String heatingFailMsg = "Failure"; + public volatile double[] heatingX; + public volatile double[] heatingY; + public volatile int heatingSamples; + public Data(ResolvedTestingUnit x) throws Throwable { + start = System.currentTimeMillis(); + this.x = x; + group = x.getGroup(); + path = x.getDisplayPath(); + link = x.getPersistentLink(); + Boolean b; + String s=null,t=null; + Stats st; + String airflowMaxHeat = null; + String airflowMaxCool = null; + hasFan = x.hasMapping(tagSFSSLockFlag) + && x.hasMapping(tagSFSSLockValue) + && x.hasMapping(tagSFST); + hasDamper = x.hasMapping(tagAirflow) + && x.hasMapping(tagAirflowLockFlag) + && x.hasMapping(tagAirflowLockValue) + && x.hasMapping(tagAirflowMaxCool) + && x.hasMapping(tagAirflowMaxHeat) + && x.hasMapping(tagDamperLockFlag) + && x.hasMapping(tagDamperLockValue) + && x.hasMapping(tagDamperPosition); + hasHeatAO = x.hasMapping(tagHeatAOLockFlag) + && x.hasMapping(tagHeatAOLockValue) + && x.hasMapping(tagHeatAOPosition) + && x.hasMapping(tagLAT); + hasPump = x.hasMapping(tagPumpCmdLockFlag) + && x.hasMapping(tagPumpCmdLockValue) + && x.hasMapping(tagPumpRevLockFlag) + && x.hasMapping(tagPumpRevLockValue) + && x.hasMapping(tagPumpStatus) + && x.hasMapping(tagLAT); + hasEAT = x.hasMapping(tagEAT); + if (hasFan && testFans || hasDamper && testDampers){ + // If we're going to test fans or dampers, first we make an attempt to shut-off all heating and cooling elements + if (hasHeatAO){ + x.setValueAutoMark(tagHeatAOLockValue,0); + x.setValueAutoMark(tagHeatAOLockFlag,true); + } + if (hasPump){ + x.setValueAutoMark(tagPumpCmdLockValue,0); + x.setValueAutoMark(tagPumpCmdLockFlag,true); + } + if (hasHeatAO){ + Thread.sleep(30000); + } + if (hasPump){ + waitFor(180000, 3000, tagPumpStatus, new Predicate(){ + public boolean test(String s){ + return s.equals("0"); + } + }); + } + } + if (hasFan && testFans) fanTest: { + // Test the fan by locking it off and then on + if (!x.setValueAutoMark(tagSFSSLockValue, 0) || !x.setValueAutoMark(tagSFSSLockFlag, true)){ + fanError = true; break fanTest; + } + b = waitFor(180000, 3000, tagSFST, new Predicate(){ + public boolean test(String s){ + return s.equals("0"); + } + }); + if (b==null){ + fanError = true; break fanTest; + } + fanStopTest = b; + if (!x.setValueAutoMark(tagSFSSLockValue, 1)){ + fanError = true; break fanTest; + } + b = waitFor(180000, 3000, tagSFST, new Predicate(){ + public boolean test(String s){ + return s.equals("1"); + } + }); + if (b==null){ + fanError = true; break fanTest; + } + fanStartTest = b; + } else if (hasFan && (hasDamper && testDampers || hasHeatAO && testHeating || hasPump && testHeating)){ + // If we're going to test dampers or heating/cooling elements, then we lock the fan on + if (x.setValueAutoMark(tagSFSSLockValue, 1) && x.setValueAutoMark(tagSFSSLockFlag, true)){ + b = waitFor(180000, 3000, tagSFST, new Predicate(){ + public boolean test(String s){ + return s.equals("1"); + } + }); + if (b!=null && b){ + fanStartTest = true; + } + } + } + if (hasDamper && testDampers) damperTest: { + // Test the damper by locking it to 0%, and then measuring the airflow at 5% increment intervals + try{ + if (airflowMaxCool==null && (airflowMaxCool=x.getValue(tagAirflowMaxCool))==null){ + damperError = true; break damperTest; + } + airflowMaxCoolValue = Double.parseDouble(airflowMaxCool); + airflowY = new Stats[airflowX.length]; + for (int i=0;i(){ + public boolean test(String s){ + return Math.abs(Double.parseDouble(s)-pos)<1; + } + }); + if (b==null){ + damperError = true; break damperTest; + }else if (!b){ + damperResponse = false; break damperTest; + } + if ((st = evaluate(airflowSamples, 2000, tagAirflow))==null){ + damperError = true; break damperTest; + } + airflowY[i] = st; + } + }catch(NumberFormatException e){ + Initializer.log(e); + damperError = true; + } + } + if (hasHeatAO && testHeating) heatTest: { + // Test heating AO by locking to 0%, waiting for stabilization, locking to 100%, and measuring the temperature at 10 second intervals + // If a damper exists, we lock it to the heating maximum airflow parameter + // We ensure there is sufficient airflow at every interval of the test (e.g, to prevent fires / overheating) + try{ + if (!fanStartTest && !hasDamper){ + heatingFailure = true; + heatingFailMsg = "Loss of Airflow"; + break heatTest; + } + if ((s=x.getValue(tagHeatAOPosition))==null){ + heatingError = true; break heatTest; + } + final double initialPosition = Double.parseDouble(s); + if (!x.setValueAutoMark(tagHeatAOLockValue,0) || !x.setValueAutoMark(tagHeatAOLockFlag,true)){ + heatingError = true; break heatTest; + } + if (hasDamper){ + final long lim = System.currentTimeMillis()+30000L+(long)(initialPosition*6000); + if (airflowMaxHeat==null && (airflowMaxHeat=x.getValue(tagAirflowMaxHeat))==null){ + heatingError = true; break heatTest; + } + airflowMaxHeatValue = Math.max(Double.parseDouble(airflowMaxHeat),150); + if (!x.setValueAutoMark(tagAirflowLockValue, airflowMaxHeatValue) || !x.setValueAutoMark(tagDamperLockFlag, false) || !x.setValueAutoMark(tagAirflowLockFlag, true)){ + heatingError = true; break heatTest; + } + waitFor(240000, 3000, tagAirflow, new Predicate(){ + public boolean test(String s){ + return Math.abs(Double.parseDouble(s)-airflowMaxHeatValue)<50; + } + }); + final long dif = lim-System.currentTimeMillis(); + if (dif>0){ + Thread.sleep(dif); + } + }else{ + Thread.sleep(30000L+(long)(initialPosition*6000)); + } + s = "0"; + if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ + heatingError = true; break heatTest; + } + final long startTime = System.currentTimeMillis(); + heatingX = new double[61]; + heatingY = new double[heatingX.length]; + heatingSamples = heatingX.length; + heatingX[0] = 0; + heatingY[0] = Double.parseDouble(t)-Double.parseDouble(s); + if (!x.setValueAutoMark(tagHeatAOLockValue,100)){ + heatingError = true; break heatTest; + } + double yMax = 0; + double yAvg = 0; + double lat = 0; + long time = 0; + for (int i=1,j;ihighLimit){ + heatingSamples = i+1; + break; + } + if (heatingY[i]>yMax){ + yMax = heatingY[i]; + } + if (i>21){ + yAvg = 0; + for (j=0;j<8;++j){ + yAvg+=heatingY[i-j-3]; + } + yAvg/=8; + if (yAvg+yMax/50>(heatingY[i]+heatingY[i-1]+heatingY[i-2])/3){ + heatingSamples = i+1; + break; + } + } + } + heatingY[0] = 0; + }catch(NumberFormatException e){ + Initializer.log(e); + heatingError = true; + }finally{ + x.setValueAutoMark(tagHeatAOLockValue,0); + } + } + if (hasPump && testHeating && !hasHeatAO) heatTest: { + try{ + if (!fanStartTest && !hasDamper){ + heatingFailure = true; + heatingFailMsg = "Loss of Airflow"; + break heatTest; + } + if (!x.setValueAutoMark(tagPumpRevLockValue,0) || !x.setValueAutoMark(tagPumpRevLockFlag,true) || !x.setValueAutoMark(tagPumpCmdLockValue,0) || !x.setValueAutoMark(tagPumpCmdLockFlag,true)){ + heatingError = true; break heatTest; + } + b = waitFor(180000, 3000, tagPumpStatus, new Predicate(){ + public boolean test(String s){ + return s.equals("0"); + } + }); + if (b==null){ + heatingError = true; break heatTest; + }else if (!b){ + heatingFailure = true; + heatingFailMsg = "Compressor Stop Failure"; + break heatTest; + } + Thread.sleep(480000L); + s = "0"; + heatingX = new double[181]; + heatingY = new double[heatingX.length]; + heatingSamples = heatingX.length; + heatingX[0] = 0; + heatingY[0] = 0; + for (int i=0;i<4;++i){ + Thread.sleep(3000); + if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ + heatingError = true; break heatTest; + } + heatingY[0]+=Double.parseDouble(t)-Double.parseDouble(s); + } + heatingY[0]/=4; + final long startTime = System.currentTimeMillis(); + if (!x.setValueAutoMark(tagPumpCmdLockValue,1)){ + heatingError = true; break heatTest; + } + String u = ""; + int pumpStart = -1; + int swap = -1; + boolean swapped = false; + boolean firstCooling = true; + double yMax=0; + double yMin=0; + double sum=0; + double yAvg=0; + double yAvg2=0; + long time = 0; + double lat = 0; + for (int i=1,j;i>1)-5; + }else if (i>18){ + heatingFailure = true; + heatingFailMsg = "Compressor Start Failure"; + break heatTest; + } + } + if (!swapped && i>=swap && swap!=-1){ + swapped = true; + swap = i+30; + firstCooling = sum<=0; + if (!x.setValueAutoMark(tagPumpRevLockValue,1)){ + heatingError = true; break heatTest; + } + } + time = System.currentTimeMillis(); + if (hasEAT && (s=x.getValue(tagEAT))==null || (t=x.getValue(tagLAT))==null){ + heatingError = true; break heatTest; + }else if ((b=checkAirflow())==null){ + heatingError = true; break heatTest; + }else if (!b){ + heatingFailure = true; + heatingFailMsg = "Loss of Airflow"; + break heatTest; + } + lat = Double.parseDouble(t); + heatingX[i] = (time-startTime)/60000.0; + heatingY[i] = lat-Double.parseDouble(s)-heatingY[0]; + if (pumpStart!=-1 && (lat>highLimit || latyMax){ + yMax = heatingY[i]; + } + if (heatingY[i]pumpStart && pumpStart!=-1 || swapped && i>swap){ + yAvg = 0; + for (j=0;j<10;++j){ + yAvg+=heatingY[i-j-5]; + } + yAvg/=10; + yAvg2 = (heatingY[i]+heatingY[i-1]+heatingY[i-2]+heatingY[i-3]+heatingY[i-4])/5; + if (swapped){ + if (firstCooling && yAvg+yMax/50>yAvg2 || !firstCooling && yAvg+yMin/500 && yAvg+yMax/50>yAvg2 || sum<=0 && yAvg+yMin/5090){ + return true; + } + } + Thread.sleep(2000); + } + } + return false; + } + private Boolean waitFor(long timeout, long interval, String tag, Predicate test) throws Throwable { + final long lim = System.currentTimeMillis()+timeout; + String s; + do { + if ((s=x.getValue(tag))==null){ + return null; + } + if (test.test(s)){ + return true; + } + if (System.currentTimeMillis()>=lim){ + break; + } + Thread.sleep(interval); + } while (System.currentTimeMillis()