Challenge Overview

Challenge Overview

The Green Button Standard is a secure way of transmitting energy usage information developed by the United States Department of Energy.

The goal of this challenge is to develop a Ruby based gem to allow the retrieval of Green Button XML formatted data, process the data, persist it in database and return data as Ruby objects.

This follows the path known as Green Button Connect in the Green Button Documentation.

Challenge Requirements

You are developing a Ruby based gem in this challenge that retrieves Retail Customer data using GreenButton RESTful API.

Before getting started coding, you are encouraged to look at this page that gives overview about GreenButton Concept, API and Entities.

Technology Stack

  • Ruby on Rails 3.2

  • Ruby 2.1.5

  • Postgres 9.4

General Notes

  • This version will only handle UsagePoints of service category (kind) = 0 (Electricity), if the downloaded data is not of type Electricity then return error to caller stating that we only support Electricity data in this version.

    • For more information about UsagePoints kinds, refer to this xsd file (ServiceKind type), the file has rich documentation about the types in GreenButton.

  • All dates are stored in UTC format in database.

  • You can find details about Greenbutton model definition in this page.

  • Logging of information/errors, and transactions should be handled properly.

Demo Page

Create simple ruby on rails application that demonstrates the usage of the ruby gem, note the following :

  • A text field for green button access token.

    • Access to Green Button APIs requires an OAuth2 Access Token. Read more about Access Tokens and the various Data Custodian Roles we are only using access_token (individual retail customer access) in this challenge.

    • Green Button APIs are available in a Sandbox server, this server does not have a live OAuth 2.0 Server to issue access tokens, you will use predefined list of tokens available in GreenButton Sandbox, mainly you are interested in access_token type tokens.

  • Add a panel for each method implemented in this challenge with fields needed as input arguments to the method.

    • It will have button to submit a request.

    • It will have a text area to render response.

Here is sample of page, with 15 minutes as interval is selected to be download :

Expected Gem Usage

The gem should have a single module GreenButton, sample usage would look like this :

require ‘greenbutton’

gb = GreenButton.download_data(access_token, resource_uri,.. some other parameters .. )

The returned result represents the wrapped greenbutton XML object with all related information downloaded in the XML file..

Model Definition

In the challenge we are persisting all data we retrieve from Green Button XML in the same structure.

Following are the ruby models definition (it will also have corresponding table in Postgres with same naming convention)

  • gb_usage_point

    • id (parsed from rel="self" link)

    • kind (parsed from <espi:kind>0</espi:kind> - electricity for now)

    • subscription_id (parsed from the passed in resourceUri)

    • meter_reading (represents associated meter_reading object)

    • local_time_parameters (represents associated local_time_parameters object)

    • electricty_power_usage_summary (represents associated electricty_power_usage_summary object)

  • gb_meter_reading

    • id

    • reading_type_id

    • accumulation_behaviour

    • commodity

    • currency

    • data_qualifier

    • flow_direction

    • interval_length

    • kind

    • phase

    • power_of_ten_multiplier

    • time_attribute

    • uom

  • gb_local_time_parameters

    • id

    • dst_end_rule

    • dst_offset

    • dst_start_rule

    • tz_offset

  • gb_electricty_power_usage_summary

    • id

    • duration

    • start_time

    • bill_last_period

    • bill_to_date

    • cost_additional_last_period

    • currency

    • overall_consumption_last_period_power_of_ten_multiplier

    • overall_consumption_last_period_uom

    • overall_consumption_last_period_value

    • current_billing_period_overall_consumption_power_of_ten_multiplier

    • current_billing_period_overall_consumption_uom

    • current_billing_period_overall_consumption_timestamp

    • current_billing_period_overall_consumption_value

    • quality_of_reading

    • status_time_stamp

  • gb_interval_block

    • id

    • start_time

    • end_time

    • usage_point_id

    • readings (represents array of interval_block_reading entities)

  • gb_interval_block_reading

    • id

    • aggregation_type (enum: default, 15_min, 1_d, 1_m)

      • the default value is the interval length in the returned XML by GreenButton API.

    • cost

    • start_time

    • value

Note that all IDs fields are parsed from rel=”self” link the xml data.

Parsing the XML response

The GreenButton Wrapper Module

  • Define the module with name : GreenButton it exposes the following functions

    • download_data

      • This function downloads customer data from GreenButton

      • This function will have the following parameters :

        • access_token : represents the retail customer access token

        • resource_uri : represents the retail customer resourceURI

        • interval_start_time (optional) : represents the start date to retrieve data. corresponds to published-min in the API endpoint query string parameter.

        • interval_end_time (optional) : represents the end date to retrieve data. corresponds to published-max in the API endpoint query string parameter.

        • aggregation_type (optional) represents the target interval length reading to convert the data readings to. it is optional, the allowed values are (15 minutes, 1 day, 1 month), can be enum.

      • parameters should be validated against their proper types.

      • The method will call the GreenButton API using the passed resourceURI and pass accessToken in header ‘Authorization’. and set the optional intervals if present.

      • The XML response from API call will be passed to target Parser based on the service category (kind), we only support Electricity in this challenge.

      • Build  a Parser to handle parsing the returned XML. The referenced gem ruby library above should be helpful.

      • If aggregation_type is present :

        • Calculate the target number of distinct interval block readings, i.e. say we have interval data blocks from 12:00:00 AM 3-15-2015 to 12:00:00 AM 3-18-2015,  15 minutes is the target aggregation type, then the number of interval blocks readings is ( 4 readings/hr x 24 hrs x 3d) =  288.

        • If target aggregation type (i.e. 15 minutes) is less than the returned interval length (i.e. 1 hour) then an algorithm should be dividing into the target interval aggregation type (i.e. for each hour it will be divided into 4 interval 15 minutes interval : start time, cost, and value should be calculated).

        • If target aggregation type (i.e. 1 hour) is greater than the returned interval length (i.e. 15 minutes) then an algorithm should do aggregation (i.e. we need four 15-minutes interval readings to calculate the 1 hour reading interval : start time, cost, and value should be calculated).

        • Update the associated interval_block_readings to reference the new calculated interval_block_readings objects.

          • the interval_block_reading#aggregation_type will be equal to the aggregation_type parameter.

        • Update gb_meter_reading#interval_length to reflect the new interval length (the aggregation type).

      • Store the data into database and return it.

        • If there are already records for the returned data, then perform update database operation.

      • The response will be array of gb_usage_points.

    • retrieve_data

      • This function retrieves the persisted green button data, applies some processing to it based on aggregation type, and returns it.

      • The parameters are :

        • subscription_id represents the retail customer subscription id, corresponds to gb_usage_point#subscription_id field

        • aggregation_type (optional) represents the target interval length reading. it is optional, the allowed values are (15 minutes, 1 day, 1 month), can be enum. If not passed, then it should beh the interval length of the returned readings.

        • interval_start_time (optional) : represents the start date used to search interval block data.

        • interval_end_time (optional) : represents the end date to search interval block data.

      • This method will execute the following logic :

        • Parameters should be validated against their proper types.

        • Retrieve all data of the given aggregation_type and subscrpition_id where interval_start_time <= interval_block(s) start/end <= interval_end_time.

        • Return the array of gb_usage_point objects.

Data Validation

As part of the data aggregation process check for zero/null/NaN/absent values in the data and filter them, and update corresponding interval_block_reading to store NULL for all cost/value fields, and add new flag attribute (isMissing) and set it to true.

Aggregation Algorithm

Please note that GreenButton supports following interval lengths (durations): https://github.com/energyos/OpenESPI-Common-java/blob/master/etc/espiDerived.xsd#L3098-L3354

So your algorithm should consider these intervals only. If duration is not among these durations documented in the XSD file, then return error.

Ruby API Client Framework

You will use Faraday to communicate with the GreenButton API.

Abstracting

Please make sure to create mixin to include the common code/functionality.

Setting Up the Gem

Use Bundler to take care of gem dependencies.

A standard folder structure would look like this :

  • Gemfile

  • LICENSE.txt

  • README.md

  • Rakefile

  • greenbutton.gemspec

  • lib

    • greenbutton

      • version.rb

      • <class-name>.rb

      • model

        • <model-name>.rb

      • greenbutton.rb (the module entry point)

Writing Tests

All of your code should be test covered (RSpec preferred).

As mentioned above, you can use the Sandbox or host the sample data to test your solution.

If you see any problem with sandbox stopped behaving normally, post in challenge forums, and we will reset it (Sandbox).

Also since the module accepts the API endpoint to be executed as input parameter, you can use sample data (check References section below) instead of hitting the sandbox directly.

Documentation

Because other programmers will be working with your code, and incorporating it into their projects, all functions must be documented in detail in the code (TomDoc preferred - In order to generate HTML properly you will need to use Yard TomDoc).

Coding Standard

Follows coding standards listed here:

https://github.com/copycopter/style-guide

Readme

Provide a detailed readme file using Markdown language with following information :

  • Overview

  • Setup Prerequisites

  • How to install

  • Usage Example

  • How to run Demo and Verify results

  • Reference to GreenButton API Documentation

  • Reference this Ruby Gem Documentation

  • Any details about any limitations of your solution.

Please note, we're judging this competition not just on the code, but also on the quality of the documentation, test coverage, and ease of use.

References



Final Submission Guidelines

Deliverable

  • All source code files and scripts that address the challenge requirement.

  • Detailed readme file as clarified above.

ELIGIBLE EVENTS:

2015 topcoder Open

Review style

Final Review

Community Review Board

Approval

User Sign-Off

ID: 30049511