Class: URBANopt::REopt::REoptLiteAPI

Inherits:
Object
  • Object
show all
Defined in:
lib/urbanopt/reopt/reopt_lite_api.rb

Instance Method Summary collapse

Constructor Details

#initialize(nrel_developer_key = nil, use_localhost = false) ⇒ REoptLiteAPI

REoptLiteAPI manages submitting optimization tasks to the REopt Lite API and recieving results. Results can either be sourced from the production REopt Lite API with an API key from developer.nrel.gov, or from a version running at localhost.

parameters:
  • use_localhost - Bool - If this is true, requests will be sent to a version of the REopt Lite API running on localhost. Default is false, such that the production version of REopt Lite is accessed.

  • nrel_developer_key - String - API key used to access the REopt Lite APi. Required only if localhost is false. Obtain from developer.nrel.gov/signup/



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/urbanopt/reopt/reopt_lite_api.rb', line 55

def initialize(nrel_developer_key = nil, use_localhost = false)
  @use_localhost = use_localhost
  if @use_localhost
    @uri_submit = URI.parse('http//:127.0.0.1:8000/v1/job/')
  else
    if [nil, '', '<insert your key here>'].include? nrel_developer_key
      if [nil, '', '<insert your key here>'].include? DEVELOPER_NREL_KEY
        raise 'A developer.nrel.gov API key is required. Please see https://developer.nrel.gov/signup/ then update the file urbanopt-reopt-gem/developer_nrel_key.rb'
      else
        nrel_developer_key = DEVELOPER_NREL_KEY
      end
    end
    @nrel_developer_key = nrel_developer_key
    @uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/v1/job/?api_key=#{@nrel_developer_key}")
    # initialize @@logger
    @@logger ||= URBANopt::REopt.reopt_logger
  end
end

Instance Method Details

#check_connection(data) ⇒ Object

Checks if a optimization task can be submitted to the REopt Lite API

parameters:
  • data - Hash - Default REopt Lite formatted post containing at least all the required parameters.

return:

Bool - Returns true if the post succeeeds. Otherwise returns false.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/urbanopt/reopt/reopt_lite_api.rb', line 115

def check_connection(data)
  header = { 'Content-Type' => 'application/json' }
  http = Net::HTTP.new(@uri_submit.host, @uri_submit.port)
  if !@use_localhost
    http.use_ssl = true
    end

  request = Net::HTTP::Post.new(@uri_submit, header)
  request.body = data.to_json

  # Send the request
  response = make_request(http, request)

  if !response.is_a?(Net::HTTPSuccess)
    @@logger.error('Check_connection Failed')
    raise 'Check_connection Failed'
  end
  return true
end

#make_request(http, r, max_tries = 3) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/urbanopt/reopt/reopt_lite_api.rb', line 91

def make_request(http, r, max_tries = 3)
  result = nil
  tries = 0
  while tries < max_tries
    begin
         result = http.request(r)
         tries = 4
       rescue StandardError
         tries += 1
       end
  end
  return result
end

#reopt_request(reopt_input, filename) ⇒ Object

Completes a REopt Lite optimization. From a formatted hash, an optimization task is submitted to the API. Results are polled at 5 second interval until they are ready or an error is returned from the API. Results are written to disk.

parameters:
  • reopt_input - Hash - REopt Lite formatted post containing at least required parameters.

  • filename - String - Path to file that will be created containing the full REopt Lite response.

return:

Bool - Returns true if the post succeeeds. Otherwise returns false.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/urbanopt/reopt/reopt_lite_api.rb', line 148

def reopt_request(reopt_input, filename)
  description = reopt_input[:Scenario][:description]

  @@logger.info("Submitting #{description} to REopt Lite API")

  # Format the request
  header = { 'Content-Type' => 'application/json' }
  http = Net::HTTP.new(@uri_submit.host, @uri_submit.port)
  if !@use_localhost
    http.use_ssl = true
  end
  request = Net::HTTP::Post.new(@uri_submit, header)
  request.body = reopt_input.to_json

  # Send the request
  response = make_request(http, request)

  # Get UUID
  run_uuid = JSON.parse(response.body)['run_uuid']

  if File.directory? filename
    if run_uuid.nil?
      run_uuid = 'error'
    end
    if run_uuid.downcase.include? 'error'
      run_uuid = "error#{SecureRandom.uuid}"
    end
    filename = File.join(filename, "#{description}_#{run_uuid}.json")
    @@logger.info("REopt results saved to #{filename}")
  end

  if response.code != '201'
    File.open(filename, 'w') do |f|
      f.write(response.body)
    end
    raise "Error in REopt optimization post - see #{filename}"
  end

  # Poll results until ready or error occurs
  status = 'Optimizing...'
  uri = uri_results(run_uuid)
  http = Net::HTTP.new(uri.host, uri.port)
  if !@use_localhost
    http.use_ssl = true
  end

  request = Net::HTTP::Get.new(uri.request_uri)

  while status == 'Optimizing...'
    response = make_request(http, request)
    data = JSON.parse(response.body)
    sizes = (data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Storage']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0)
    status = data['outputs']['Scenario']['status']

    sleep 5
  end

  _max_retry = 5
  _tries = 0
  (check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
  while (_tries < _max_retry) && check_complete
    sleep 1
    response = make_request(http, request)
    data = JSON.parse(response.body)
    sizes = (data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Storage']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0)
    (check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
    _tries += 1
  end

  File.open(filename, 'w') do |f|
    f.write(data.to_json)
  end

  if status == 'optimal'
    return data
  end

  error_message = data['messages']['error']
  raise "Error from REopt API - #{error_message}"
end

#uri_results(run_uuid) ⇒ Object

URL of the results end point for a specific optimization task

parameters:
  • run_uuid - String - Unique run_uuid obtained from the REopt Lite job submittal URL for a specific optimization task.

return:

URI - Returns URI object for use in calling the REopt Lite results endpoint for a specifc optimization task.



84
85
86
87
88
89
# File 'lib/urbanopt/reopt/reopt_lite_api.rb', line 84

def uri_results(run_uuid) # :nodoc:
  if @use_localhost
    return URI.parse("http://127.0.0.1:8000/v1/job/#{run_uuid}/results")
  end
  return URI.parse("https://developer.nrel.gov/api/reopt/v1/job/#{run_uuid}/results?api_key=#{@nrel_developer_key}")
end