From 39f7d301afd3a325a87d31dadd10925b5c2f34cd Mon Sep 17 00:00:00 2001 From: indu-manogaran Date: Mon, 9 Jan 2023 02:27:05 -0700 Subject: [PATCH 1/5] endpoints edits for v3 --- job/urls.py | 5 +++++ job/views.py | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/job/urls.py b/job/urls.py index f16f899f2..ec4c7282d 100644 --- a/job/urls.py +++ b/job/urls.py @@ -28,6 +28,7 @@ # OF THE POSSIBILITY OF SUCH DAMAGE. # ********************************************************************************* from . import views +from reo import views as reoviews from django.urls import re_path urlpatterns = [ @@ -37,4 +38,8 @@ re_path(r'^job/outputs/?$', views.outputs), re_path(r'^chp_defaults/?$', views.chp_defaults), re_path(r'^simulated_load/?$', views.simulated_load), + + re_path(r'^invalid_urdb/?$', reoviews.invalid_urdb), + re_path(r'^emissions_profile/?$', reoviews.emissions_profile), + re_path(r'^annual_kwh/?$', reoviews.annual_kwh), ] diff --git a/job/views.py b/job/views.py index ad77e8dcd..d6eccc754 100644 --- a/job/views.py +++ b/job/views.py @@ -407,6 +407,19 @@ def simulated_load(request): value = request.GET.get(key) if value is not None: inputs[key] = value + + #removed all error messages when copying code from reo.views + if inputs["load_type"] == "electric": + + #Annual loads + if 'annual_kwh' in request.GET.keys(): + inputs["annual_kwh"] = float(request.GET.get('annual_kwh')) + + #Monthly loads + monthly_totals_kwh = None + if 'monthly_totals_kwh[0]' in request.GET.keys(): + monthly_totals_kwh = [request.GET.get('monthly_totals_kwh[{}]'.format(i)) for i in range(12)] + inputs["monthly_totals_kwh"] = [float(i) for i in monthly_totals_kwh] julia_host = os.environ.get('JULIA_HOST', "julia") http_jl_response = requests.get("http://" + julia_host + ":8081/simulated_load/", json=inputs) From 220fe8c5ecd6828bf44e9ecbadd960489419c3df Mon Sep 17 00:00:00 2001 From: bill-becker Date: Mon, 9 Jan 2023 21:40:18 -0700 Subject: [PATCH 2/5] Force data type conversions in /dev/simulated_load These should cover all load_type variables --- job/views.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/job/views.py b/job/views.py index d6eccc754..860395360 100644 --- a/job/views.py +++ b/job/views.py @@ -364,35 +364,37 @@ def simulated_load(request): raise ValueError("{} is not a valid input parameter".format(key)) # Build inputs dictionary to send to http.jl /simulated_load endpoint inputs = {} + # Required - will throw a Missing Error if not included inputs["latitude"] = float(request.GET['latitude']) # need float to convert unicode inputs["longitude"] = float(request.GET['longitude']) + # Optional load_type - will default to "electric" inputs["load_type"] = request.GET.get('load_type') # This parses the GET request way of sending a list/array for doe_reference_name, - # i.e. doe_reference_name[0], doe_reference_name[1], etc + # i.e. doe_reference_name[0], doe_reference_name[1], etc along with percent_share[0], percent_share[1] if 'doe_reference_name' in request.GET.keys(): - inputs["doe_reference_name"] = request.GET.get('doe_reference_name') + inputs["doe_reference_name"] = str(request.GET.get('doe_reference_name')) elif 'doe_reference_name[0]' in request.GET.keys(): idx = 0 doe_reference_name = [] percent_share_list = [] while 'doe_reference_name[{}]'.format(idx) in request.GET.keys(): - doe_reference_name.append(request.GET['doe_reference_name[{}]'.format(idx)]) + doe_reference_name.append(str(request.GET['doe_reference_name[{}]'.format(idx)])) if 'percent_share[{}]'.format(idx) in request.GET.keys(): percent_share_list.append(float(request.GET['percent_share[{}]'.format(idx)])) idx += 1 inputs["doe_reference_name"] = doe_reference_name - inputs["percent_share_list"] = percent_share_list + inputs["percent_share"] = percent_share_list # When wanting cooling profile based on building type(s) for cooling, need separate cooling building(s) if 'cooling_doe_ref_name' in request.GET.keys(): - inputs["cooling_doe_ref_name"] = request.GET.get('cooling_doe_ref_name') + inputs["cooling_doe_ref_name"] = str(request.GET.get('cooling_doe_ref_name')) elif 'cooling_doe_ref_name[0]' in request.GET.keys(): idx = 0 cooling_doe_ref_name = [] cooling_pct_share_list = [] while 'cooling_doe_ref_name[{}]'.format(idx) in request.GET.keys(): - cooling_doe_ref_name.append(request.GET['cooling_doe_ref_name[{}]'.format(idx)]) + cooling_doe_ref_name.append(str(request.GET['cooling_doe_ref_name[{}]'.format(idx)])) if 'cooling_pct_share[{}]'.format(idx) in request.GET.keys(): cooling_pct_share_list.append(float(request.GET['cooling_pct_share[{}]'.format(idx)])) idx += 1 @@ -406,20 +408,12 @@ def simulated_load(request): if key_type in key: value = request.GET.get(key) if value is not None: - inputs[key] = value - - #removed all error messages when copying code from reo.views - if inputs["load_type"] == "electric": - - #Annual loads - if 'annual_kwh' in request.GET.keys(): - inputs["annual_kwh"] = float(request.GET.get('annual_kwh')) - - #Monthly loads - monthly_totals_kwh = None - if 'monthly_totals_kwh[0]' in request.GET.keys(): - monthly_totals_kwh = [request.GET.get('monthly_totals_kwh[{}]'.format(i)) for i in range(12)] - inputs["monthly_totals_kwh"] = [float(i) for i in monthly_totals_kwh] + if type(value) == list: + monthly_list = [request.GET.get(key+'[{}]'.format(i)) for i in range(12)] + k = key.split('[')[0] + inputs[k] = [float(i) for i in monthly_list] + else: + inputs[key] = float(value) julia_host = os.environ.get('JULIA_HOST', "julia") http_jl_response = requests.get("http://" + julia_host + ":8081/simulated_load/", json=inputs) From 4819f48a7f0072258bab81292dbbdf9262dcc9e6 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Mon, 9 Jan 2023 21:42:15 -0700 Subject: [PATCH 3/5] Convert data types to correct after JSON parse --- julia_src/http.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/julia_src/http.jl b/julia_src/http.jl index 2bff440aa..20ddaf1cc 100644 --- a/julia_src/http.jl +++ b/julia_src/http.jl @@ -201,6 +201,17 @@ end function simulated_load(req::HTTP.Request) d = JSON.parse(String(req.body)) + # Arrays in d are being parsed as type Vector{Any} instead of fixed type Vector{String or <:Real} without conversion + for key in ["doe_reference_name", "cooling_doe_ref_name"] + if key in keys(d) && typeof(d[key]) <: Vector{} + d[key] = convert(Vector{String}, d[key]) + end + end + + if "percent_share" in keys(d) && typeof(d["percent_share"]) <: Vector{} + d["percent_share"] = convert(Vector{Float64}, d["percent_share"]) + end + @info "Getting CRB Loads..." data = Dict() error_response = Dict() From 1989ba064d0fa67a6f79bd0bff663f1a28d01169 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Mon, 9 Jan 2023 21:42:42 -0700 Subject: [PATCH 4/5] Call /dev/simulated_load instead of http.jl endpoint directly By calling /dev/sim... which calls the http.jl endpoint, we include testing of type parsing and conversions that django does before calling http.jl endpoint --- job/test/test_http_endpoints.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/job/test/test_http_endpoints.py b/job/test/test_http_endpoints.py index 69473209c..d5abcfbec 100644 --- a/job/test/test_http_endpoints.py +++ b/job/test/test_http_endpoints.py @@ -55,10 +55,9 @@ def test_simulated_load(self): "longitude": -122.45 } - # Direct call of the http.jl endpoint /chp_defaults - julia_host = os.environ.get('JULIA_HOST', "julia") - response = requests.get("http://" + julia_host + ":8081/simulated_load/", json=inputs) - http_response = response.json() + # The /dev/simulated_load endpoint calls the http.jl /simulated_load endpoint + response = self.api_client.get(f'/dev/simulated_load', data=inputs) + http_response = json.loads(response.content) # Call to the v2 /simulated_load to check for consistency resp = self.api_client.get(f'/v2/simulated_load', data=inputs) @@ -73,10 +72,9 @@ def test_simulated_load(self): inputs["percent_share[0]"] = 25.0 inputs["percent_share[1]"] = 100.0 - inputs["percent_share[0]"] - # Direct call of the http.jl endpoint /chp_defaults - julia_host = os.environ.get('JULIA_HOST', "julia") - response = requests.get("http://" + julia_host + ":8081/simulated_load/", json=inputs) - http_response = response.json() + # The /dev/simulated_load endpoint calls the http.jl /simulated_load endpoint + response = self.api_client.get(f'/dev/simulated_load', data=inputs) + http_response = json.loads(response.content) # Call to the v2 /simulated_load to check for consistency resp = self.api_client.get(f'/v2/simulated_load', data=inputs) From 2c212a42a14d899f2a95ac03d95a4be21081a7d6 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Mon, 9 Jan 2023 21:45:48 -0700 Subject: [PATCH 5/5] Remove redundant /annual_kwh endpoint use /simulated_load instead /simulated_load endpoint returns the annual_kwh and uses the Julia functions from http.jl so it's more in sync with REopt.jl --- job/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/job/urls.py b/job/urls.py index ec4c7282d..7964523c9 100644 --- a/job/urls.py +++ b/job/urls.py @@ -41,5 +41,4 @@ re_path(r'^invalid_urdb/?$', reoviews.invalid_urdb), re_path(r'^emissions_profile/?$', reoviews.emissions_profile), - re_path(r'^annual_kwh/?$', reoviews.annual_kwh), ]