Skip to content

Commit

Permalink
Merge branch 'master' into issue406_spawnSupport
Browse files Browse the repository at this point in the history
  • Loading branch information
dhblum committed Jul 19, 2022
2 parents dde4825 + 0e9673a commit 23daae2
Show file tree
Hide file tree
Showing 35 changed files with 1,524 additions and 431 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ USER developer

WORKDIR $HOME

RUN pip install --user flask-restful==0.3.9 pandas==0.24.2 flask_cors==3.0.10
RUN pip install --user flask-restful==0.3.9 pandas==0.24.2 flask_cors==3.0.10 requests==2.27.1

RUN mkdir models && \
mkdir doc

ENV PYTHONPATH $PYTHONPATH:$HOME
ENV BOPTEST_DASHBOARD_SERVER https://api.boptest.net:8081/

CMD python restapi.py && bash

Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
Building Optimization Performance Tests

This repository contains code for the Building Optimization Performance Test framework (BOPTEST)
that is being developed as part of the IBPSA Project 1 (https://ibpsa.github.io/project1/).
that is being developed as part of the [IBPSA Project 1](https://ibpsa.github.io/project1/).

Visit the [BOPTEST Home Page](https://ibpsa.github.io/project1-boptest/) for more information about the project, software, and documentation.

## Structure
- ``/testcases`` contains test cases, including docs, models, and configuration settings.
Expand All @@ -21,11 +23,11 @@ that is being developed as part of the IBPSA Project 1 (https://ibpsa.github.io/
1) Download this repository.
2) Install [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/).
3) Build and deploy a test case using the following commands executed in the root directory of this repository and where <testcase_dir_name> is the name of the test case subdirectory located in [/testcases](https://github.com/ibpsa/project1-boptest/tree/master/testcases):
* Linux or macOS: ``$ TESTCASE=<testcase_dir_name> docker-compose up``

* Linux or macOS: ``$ TESTCASE=<testcase_dir_name> docker-compose up``
* Windows PowerShell: ``> ($env:TESTCASE="<testcase_directory>") -and (docker-compose up)``
* A couple notes:
* The first time this command is run, the image ``boptest_base`` will be built. This takes about a minute. Subsequent usage will use the already-built image and deploy much faster.
* The first time this command is run, the image ``boptest_base`` will be built. This takes about a minute. Subsequent usage will use the already-built image and deploy much faster.
* If you update your BOPTEST repository, use the command ``docker rmi boptest_base`` to remove the image so it can be re-built with the updated repository upon next deployment.
* ``TESTCASE`` is simply an environment variable. Consistent with use of docker-compose, you may also edit the value of this variable in the ``.env`` file and then use ``docker-compose up``.

Expand All @@ -52,6 +54,7 @@ that is being developed as part of the IBPSA Project 1 (https://ibpsa.github.io/

## Test Case RESTful API
- To interact with a deployed test case, use the API defined in the table below by sending RESTful requests to: ``http://127.0.0.1:5000/<request>``
- The API will return a JSON in the form ``{"status":<status_code_int>, "message":<message_str>, "payload":<relevant_return_data>}``. Status codes in ``"status"`` are integers: ``200`` for successful with or without warning, ``400`` for bad input error, or ``500`` for internal error. Data returned in ``"payload"`` is the data of interest relvant to the specific API request, while the string in ``"message"`` will report any warnings or error messages to help debug encountered problems.

Example RESTful interaction:

Expand All @@ -76,6 +79,8 @@ Example RESTful interaction:
| Receive current test scenario. | GET ``scenario`` |
| Set test scenario. Setting the argument ``time_period`` performs an initialization with predefined start time and warmup period and will only simulate for predefined duration. | PUT ``scenario`` with optional arguments ``electricity_price=<string>``, ``time_period=<string>``. See README in [/testcases](https://github.com/ibpsa/project1-boptest/tree/master/testcases) for options and test case documentation for details.|
| Receive BOPTEST version. | GET ``version`` |
| Submit KPIs, other test information, and optional string tags (up to 10) to online dashboard. Requires a formal test scenario to be completed, initialized using the PUT ``scenario`` API. | POST ``submit`` with required argument ``api_key=<string>`` and optional arguments ``tag#=<string>`` where # is an integer between 1 and 10. The API key can be obtained from the user account registered wth the online dashboard at (url coming soon).|

## Development

This repository uses pre-commit to ensure that the files meet standard formatting conventions (such as line spacing, layout, etc).
Expand Down Expand Up @@ -106,7 +111,7 @@ D. Blum, J. Arroyo, S. Huang, J. Drgona, F. Jorissen, H.T. Walnum, Y. Chen, K. B
J. Arroyo, F. Spiessens, and L. Helsen. (2022). ["Comparison of Optimal Control Techniques for Building Energy Management."](https://doi.org/10.3389/fbuil.2022.849754) *Frontiers in Built Environment* 8.

T. Marzullo, S. Dey, N. Long, J. L. Vilaplana, and G. Henze. (2022). ["A high-fidelity building performance simulation test bed for the development and evaluation of advanced controls"](https://doi.org/10.1080/19401493.2022.2058091) *Journal of Building Performance Simulation*, 15(3), 379-397.

J. Arroyo, C. Manna, F. Spiessens, and L. Helsen. (2022). ["Reinforced model predictive control (RL-MPC) for building energy management."](https://doi.org/10.1016/j.apenergy.2021.118346) *Applied Energy* 309: 118346.

J. Arroyo, C. Manna, F. Spiessens, and L. Helsen. (2021). [“An OpenAI-Gym Environment for the Building Optimization Testing (BOPTEST) Framework.”](https://www.researchgate.net/profile/Javier-Arroyo/publication/354386346_An_OpenAI-Gym_environment_for_the_Building_Optimization_Testing_BOPTEST_framework/links/613616690360302a0082ffc1/An-OpenAI-Gym-environment-for-the-Building-Optimization-Testing-BOPTEST-framework.pdf) In *Proceedings of the 17th IBPSA Conference*, Sep 1 - 3. Bruges, Belgium.
Expand Down
15 changes: 8 additions & 7 deletions examples/javascript/testcase1.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,14 @@
}
else {
console.log( "SUCCESS in getting results" );
result.value = xhr_get_result.response;
json = JSON.parse(xhr_get_result.responseText)["payload"];
result.value = JSON.stringify(json);
}
}
};
var results = {};

var results_arg='{"point_name":"TRooAir_y","start_time":0,"final_time":'+length.toString()+'}';
console.log(results_arg)
xhr_get_result.send(results_arg);

xhr_get_kpi = new XMLHttpRequest();
Expand All @@ -146,7 +147,8 @@
}
else {
console.log( "SUCCESS in getting kpi" );
kpi.value = xhr_get_kpi.response;
json = JSON.parse(xhr_get_kpi.responseText)["payload"];
kpi.value = JSON.stringify(json);
}
}
};
Expand Down Expand Up @@ -202,8 +204,9 @@
xhr.setRequestHeader("Content-type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
output.value = xhr.response;
json = JSON.parse(xhr.responseText);
json = JSON.parse(xhr.responseText)["payload"];
console.log(json)
output.value = JSON.stringify(json);
<!-- initialize the information for the select box and plotting-->
if (count ==1) {
for (key in json) {
Expand Down Expand Up @@ -231,8 +234,6 @@
point = e.target.value;
})
}


xhr.send(data);
}
};
Expand Down
13 changes: 8 additions & 5 deletions examples/javascript/testcase2.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@
}
else {
console.log( "SUCCESS in getting results" );
result.value = xhr_get_result.response;
json = JSON.parse(xhr_get_result.responseText)["payload"];
result.value = JSON.stringify(json);
}
}
};
Expand All @@ -147,7 +148,8 @@
}
else {
console.log( "SUCCESS in getting kpi" );
kpi.value = xhr_get_kpi.response;
json = JSON.parse(xhr_get_kpi.responseText)["payload"];
kpi.value = JSON.stringify(json);
}
}
};
Expand Down Expand Up @@ -188,16 +190,17 @@

data = '{"oveTSetRooHea_u":295.15,"oveTSetRooHea_activate":1, "oveTSetRooCoo_u":296.15,"oveTSetRooCoo_activate":1}'
};
console.log(data);


<!-- Advance simulation -->
xhr = new XMLHttpRequest();
xhr.open("POST", url+"advance", false);
xhr.setRequestHeader("Content-type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
output.value = xhr.response;
json = JSON.parse(xhr.responseText);
json = JSON.parse(xhr.responseText)["payload"];
console.log(json)
output.value = JSON.stringify(json);
<!-- initialize the information for the select box and plotting-->
if (count ==1) {
for (key in json) {
Expand Down
73 changes: 52 additions & 21 deletions examples/julia/testcase1.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# GENERAL PACKAGE IMPORT
# ----------------------
using HTTP, JSON, CSV, DataFrames
using HTTP, JSON, CSV, DataFrames, Dates

# TEST CONTROLLER IMPORT
# ----------------------
Expand All @@ -25,30 +25,55 @@ step = 300
# --------------------
println("TEST CASE INFORMATION ------------- \n")
# Test case name
name = JSON.parse(String(HTTP.get("$url/name").body))
println("Name:\t\t\t$name")

res = HTTP.get("$url/name")
name_status = res.status
name = JSON.parse(String(res.body))["payload"]
if name_status == 200
println("Name:\t\t\t$name['name']")
end
# Inputs available
inputs = JSON.parse(String(HTTP.get("$url/inputs").body))
println("Control Inputs:\t\t\t$inputs")
res = HTTP.get("$url/inputs")
inputs_status = res.status
inputs = JSON.parse(String(res.body))["payload"]
if inputs_status == 200
println("Control Inputs:\t\t\t$inputs")
end
# Measurements available
measurements = JSON.parse(String(HTTP.get("$url/measurements").body))
println("Measurements:\t\t\t$measurements")
res = HTTP.get("$url/measurements")
measurements_status = res.status
measurements = JSON.parse(String(res.body))["payload"]
if measurements_status == 200
println("Measurements:\t\t\t$measurements")
end

# Default simulation step
step_def = JSON.parse(String(HTTP.get("$url/step").body))
println("Default Simulation Step:\t$step_def")
res = HTTP.get("$url/measurements")
step_def_status = res.status
step_def = JSON.parse(String(res.body))["payload"]
if step_def_status == 200
println("Default Simulation Step:\t$step_def")
end

# RUN TEST CASE
#----------
println("Initializing test case simulation.")
start = Dates.now()
# Initialize test case simulation
res = HTTP.put("$url/initialize",["Content-Type" => "application/json"], JSON.json(Dict("start_time" => 0,"warmup_period" => 0)))
initialize_result=JSON.parse(String(res.body))
if !isnothing(initialize_result)
initialize_status = res.status
initialize_result=JSON.parse(String(res.body))["payload"]
if initialize_status == 200
println("Successfully initialized the simulation")
end


# Set simulation step
println("Setting simulation step to $step")

res = HTTP.put("$url/step",["Content-Type" => "application/json"], JSON.json(Dict("step" => step)))
if res.status == 200
println("Setting simulation step to $step")
end

println("Running test case ...")


Expand All @@ -62,15 +87,21 @@ for i = 1:convert(Int, floor(length/step))
u = PID.compute_control(y)
end
# Advance in simulation
global y = JSON.parse(String(HTTP.post("$url/advance", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(u);retry_non_idempotent=true).body))

res = HTTP.post("$url/advance", ["Content-Type" => "application/json"], JSON.json(u);retry_non_idempotent=true)
global y = JSON.parse(String(res.body))["payload"]
if res.status == 200
println("Successfully advanced the simulation")
end
end
println("Test case complete.")

# VIEW RESULTS
# ------------
# Report KPIs
kpi = JSON.parse(String(HTTP.get("$url/kpi").body))
res = HTTP.get("$url/kpi")
if res.status == 200
kpi = JSON.parse(String(res.body))["payload"]
end
println("KPI RESULTS \n-----------")
for key in keys(kpi)
if isnothing(kpi[key])
Expand All @@ -84,16 +115,16 @@ end
# POST PROCESS RESULTS
# --------------------
# Get result data
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "TRooAir_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "TRooAir_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))["payload"]
time = [x/3600 for x in res["time"]] # convert s --> hr
TZone = [x-273.15 for x in res["TRooAir_y"]] # convert K --> C
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "CO2RooAir_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "CO2RooAir_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))["payload"]
CO2Zone = [x for x in res["CO2RooAir_y"]]
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "PHea_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "PHea_y","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))["payload"]
PHeat = res["PHea_y"]
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "oveAct_u","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "oveAct_u","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))["payload"]
QHeat = res["oveAct_u"]
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "oveAct_activate","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))
res = JSON.parse(String(HTTP.put("$url/results", ["Content-Type" => "application/json","connecttimeout"=>30.0], JSON.json(Dict("point_name" => "oveAct_activate","start_time" => 0, "final_time" => length));retry_non_idempotent=true).body))["payload"]
uAct = res["oveAct_activate"]
tab_res=DataFrame([time,TZone,CO2Zone,PHeat,QHeat,uAct],[:time,:TRooAir_y,:CO2RooAir_y,:PHea_y,:oveAct_u,:oveAct_activate])
CSV.write("result_testcase1.csv",tab_res)
Expand Down
Loading

0 comments on commit 23daae2

Please sign in to comment.