AMEE realtime :: Uploading Data using the API

Table of Contents

Introduction
Getting Started
Curl
The AMEE AMON API Specification
Base URL
Supported Resources
Available Resource Operations

Entity Operations
Entity Representations Accepted
Entity Representations Served
Metering Point Operations
Metering Point Representations Accepted
Metering Point Representations Served
Entity/Metering Point Association Operations
Entity/Metering Point Representations Accepted
Entity/Metering Point Representations Served
Meter Operations
Meter Representations Accepted
Meter Representations Served
Entity/Meter Association Operations
Entity/Meter Representations Accepted
Entity/Meter Representations Served
Meter/Measurement Operations
Meter/Measurement Representations Accepted
Meter/Measurement Representations Served
Measurement Operations
Measurement Representations Accepted
Measurement Representations Served
Errors & HTTP Response Codes
Measurement Values
Status
Authentication
Content Types
Character Sets
Compression
Pagination


Example AMEE AMON API Calls

#1: Creating a Meter
#2: Inspecting an Existing Meter
#3: Submitting Measurement Data
Timezone Offsets for Measurement Data
#4: Retrieving Measurement Data
#5: Correcting Measurement Data
#6: Associating a Meter with a Property

Trouble-Shooting
Known Issues

 


Introduction

The AMEE AMON API can be used to upload meters & associated measurement data into the AMEE data store, and retreived for viewing in your web application. It also provides some examples of how to use the AMEE AMON API in practice.

Getting Started

In order to be able to use the AMEE AMON API to upload meters & measurement data, you will need the following things:

  1. An understanding of the AMON standard for describing meter & measurement data.
  2. The hostname of the AMEE AMON API; and
  3. A separate username and password for accessing the AMEE AMON API.

Please note that there are two possible hostnames for the AMEE AMON API – one for the test/development API (which should be used to practice your integration with the API), and one for the production data store. To demo, please use http://realtime-api-demo.amee.com/2 (demo / demo) (e.g. http://realtime-api-demo.amee.com/2/meters.json .json needed in browser)

If you don’t have log in details for the AMEE AMON API, or if you are unsure of the URLs of the two different AMEE AMON APIs (or which URL to use) please email help@amee.com, and AMEE will help to arrange access for you.

Curl

Throughout this document, the widely available curl tool has been used for all example AMEE AMON API calls. However, you are free to use any HTTP communications client, HTTP communications library, or even write your own HTTP communications code, if you wish

The AMEE AMON API Specification

Base URL

In the following API specification, all URLs are relative to the base URL. The base URL is the hostname of either the test/development API, or the production data store, followed by the AMEE AMON API version number (i.e. 2).

So, for example, in the API specification below, a (partial) URL of /meters would mean, if you were using the test/development API (with hostname metering-api-dev.amee.com), that the full URL would be http://metering-api-dev.amee.com/2/meters.

Supported Resources

The following AMON resources are supported by the AMEE AMON API.

  • Entity
    An entity is typically a property, but may also be a virtual property, e.g. one that captures all properties in a project.
  • Metering Point
    Either a billing point (i.e. a meter where a user’s bill readings are taken) or a virtual meter, which aggregates a number of other meters (e.g. a collection of sub-meters). Most users will not need to use Metering Point resources.
  • Meter
    Generally devices which automatically record & report measurements (i.e. not necessarily just gas or electricity meters). Most users will use Meter resources.
  • Measurement
    The measurements (i.e. actual device readings) for Meters.

Available Resource Operations

Throughout this section, all UUID, description, location, metadata, name, type, unit, resolution, accuracy, timestamp, value and error values are for illustration purposes only.

Entity Operations

  • Path: /entities/{entity-UUID}
  • GET: Get a representation of an entity.
    – 200 (“OK”)
  • POST: Create a new entity.
    – 201 (“Created”)
  • PUT: Update an existing entity.
    – 200 (“OK”)
  • POST
    – Append to an existing entity. The string ‘?append=true’ must be added to the URL for POST requests.

Entity Representations Accepted

{
   "entityId": string UUID,
   "description": optional string,
   "meterIds": [
      optional string UUID,
      ...
],
   "meteringPointIds": [
      optional string UUID,
...
]
}

Entity Representations Served

{
   "entityId": string UUID,   "description": optional string,
   "meterIds": [
   optional string UUID,
   ...
],
   "meteringPointIds": [
      optional string UUID,
      ...
]
}

Metering Point Operations

  • Path: /metering-points/{metering-point-UUID}
  • GET: Get a representation of a metering point.
    – 200 (“OK”)
  • POST: Create a new metering point.
    – 201 (“Created”)
  • PUT: Update an existing metering point.
    – 200 (“OK”)

Metering Point Representations Accepted

{
   "meteringPointId": string UUID,
   "description": optional string,
   "metadata": {
      optional JSON object listing metereringPoint level metadata
      e.g. MPAN, Serial Number
   }
}

Metering Point Representations Served

{
   "meteringPointId": string UUID,
   "description": optional string,
   "metadata": {
      optional JSON object listing metereringPoint level metadata
      e.g. MPAN, Serial Number
   }
}

 Entity/Metering Point Association Operations

  • Path: /entities/{entity-UUID}/metering-points/{metering-point-UUID}
  • DELETE: Unlink the metering point from the entity.
    – 200 (“OK”)

Entity/Metering Point Representations Accepted

None

Entity/Metering Point Representations Served

None

 Meter Operations

  • Path: /meters/{meter-UUIDS}
  • GET: Get a representation of a meter.
    – 200 (“OK”)
  • POST: Create a new meter.
    – 201 (“Created”)
  • PUT: Update an existing meter.
    – 200 (“OK”)

Meter Representations Accepted

{
"meterId": optional string UUID, // If included, must match the ID in the URL
"description": optional string,
"originId": optional string UUID, // If included, meter is a clone of originId
"meteringPointId": optional string UUID,
"privacy": string,
"location": {
"name": optional string,
"latitude": optional string,
"longitude": optional string
},
"metadata": {
optional JSON object
},
"readings": [
{
"type": meter type,
"unit": optional string,
"resolution": optional number,
"accuracy": optional number,
"period": optional period type // Defaults to "instant"
},
],
"measurements": [
{
"type": defined reading type,
"timestamp": RFC 3339 [2] string, // Required
"value": number, boolean or string // Typically present, "error" must be
// set if omitted
"error": string // Required if "value” omitted, forbidden otherwise
},
]
}

Meter Representations Served

{
   "meterId": string UUID,
   "description": optional string,
   "originId": optional string UUID,
   "meteringPointId": optional string UUID,
   "privacy": string,
   "location": {
      "name": optional string,
      "latitude": optional string,
      "longitude": optional string
   },
   "metadata": {
      optional JSON object
   },
   "readings": [
   {
      "type": meter type,
      "unit": string,
      "resolution": number,
      "accuracy": number,
      "period": period type
   },
   ],
"measurements": [
   {
      "type": defined reading type,
      "timestamp": RFC 3339 [2] string
      "value": number, boolean or string // Typically present, if not, "error"
      "error": string // Only present when "value” not
   },
   ]
}

 Entity/Meter Association Operations

  • Path: /entities/{entity-UUID}/meters/{meter-UUID}
  • DELETE: Unlink the meter from the entity.
    – 200 (“OK”)

Entity/Meter Representations Accepted

None

Entity/Meter Representations Served

None

 Meter/Measurement Operations

  • Path: /meters/{meter-UUID}/measurements
  • GET: Get a list of measurements.
    – 200 (“OK”)
  • POST: Add new measurements for a meter.
    – 201 (“Created”)
  • Query parameters:
    – startDate: Start of the range of measurements to retrieve (inclusive), required for GET operations, not permitted for POST operations.
    – endDate: Optional end of the range of measurements to retrieve (inclusive), required for GET operations, not permitted for POST operations.
    – raw: When “true”, raw data is returned; otherwise data returned may be an appropriately aggregated version of the raw data, based on the time range requested. Default is “false”. Optional for GET operations, not permitted for POST operations.

Meter/Measurement Representations Accepted

{
   "measurements": [
      {
         "type": defined reading type,
         "timestamp": RFC 3339 string,
         "value": number, boolean or string // Typically present, if not, "error"
         "error": string // Only present when "value” not
      },
   ]
}

Meter/Measurement Representations Served

{
   "measurements": [
      {
         "type": defined reading type,
         "timestamp": RFC 3339 string,
         "value": number, boolean or string // Typically present, if not, "error"
         "error": string // Only present when "value” not
      },
   ]
}

 

Measurement Operations

  • Path: /meters/{meter-UUID}/measurements/{reading-type}/{timestamp}
  • GET: Get a specific measurement.
    – 200 (“OK”)
  • PUT: Update/correct a specific measurement for a meter.
    – 200 (“OK”)

Measurement Representations Accepted

{
   "type": defined reading type,
   "timestamp": RFC 3339 string,
   "value": number, boolean or string // Typically present, if not, "error"
   "error": string // Only present when "value” not
}

Measurement Representations Served

{
   "type": defined reading type,
   "timestamp": RFC 3339 string,
   "value": number, boolean or string // Typically present, if not, "error"
   "error": string // Only present when "value” not
}

Errors & HTTP Response Codes

  • Unauthorised Access:
    – 401 (“Unauthorized”)
  • Invalid Query Parameters:
    – 400 (“Bad Request”)
  • Invalid Representation Provided:
    – 400 (“Bad Request”)
  • Unsupported Representation Provided (eg, XML data supplied instead of valid JSON):
    – 415 (“Unsupported Media Type”)
  • GET on a Non-existent Resource:
    – 404 (“Not Found”)
  • POST/PUT on a Non-existent Resource:
    – 404 (“Unauthorized”)

Measurement Values

Measurement values may be a number, a boolean or a string. For numerical values, the AMEE AMON API stores values in double precision format. Numbers may be supplied in standard decimal or scientific notation format, as per the JSON number object.

Status

Along with the appropriate HTTP response code, a separate ‘status’ element will also be returned in the body of the response. Eg, OK, INVALID, ERROR:

{ "status": "OK" }

Authentication

All requests must be authenticated using HTTP basic authentication.

Content Types

JSON is the only supported content type for both requests and responses. The ‘Accept’ and ‘Content-Type’ headers should always be set to ‘application/json’.

Character Sets

The body will be interpreted as UTF-8 encoded.

Compression

The request may be gzip compressed to reduce bandwidth.

Pagination

Pagination is not supported.

Example AMEE AMON API Calls

In all of the following examples, the test/development API is used. Please feel free to test these examples, and to use the test/development API to test your integration with the API; however, please also remember that this is not the production API, and as such, data uploaded using the test/development API may be deleted.

#1: Creating a Meter

In order to be able to upload measurement data to the AMEE AMON API, you will firstly need to create a meter to store the data.

To create a meter, send a POST request to the /meters path. For example, assuming the following JSON data exists in a file called create_meter.json:

{
   "description": "Test Meter #1234",
   "location": {
      "name": "test_location"
   },
   "readings":[
      {
         "type": "electricityConsumption",
         "unit": "kWh",
         "period": "instant"
      }
   ]
}

then run the command:

curl -v \   -u username:password \   -H 'Content-Type: application/json' \   -H 'Accept: application/json' \   -X POST \
   -d @create_meter.json \ http://metering-api-dev.amee.com/2/meters

 In the above example, curl is called with AMEE AMON API URL http://metering-api-dev.amee.com/2/meters, and the following options have been used:

  • -v: Verbose output, to make it easier to see what curl is doing;
  • -u: Set your AMEE AMON API username and password here;
  • -H: Tell the AMEE AMON API that the data being submitted is JSON;
  • -H: Tell the AMEE AMON API that the data returned should be JSON;
  • -X: Send an HTTP POST request to the AMEE AMON API;
  • -d: Send the JSON data from the create_meter.json file to the AMEE AMON API;

 Note that the full AMEE AMON API URL that is called (http://metering-api-dev.amee.com/2/meters,), includes a “2” in the URL, after the AMEE AMON API URL and before the path. This is the current AMEE AMON API version number, and is required for all AMEE AMON API calls.

 The JSON data sent to the AMEE AMON API above is an example of AMON formatted data that specifies a meter. It can be understood by understanding the AMON specification. However, in brief, it defines a meter that:

  • Has a physical location of test_location;
  • Takes readings that relate to the consumption of electricity;
  • Those readings are in kWh; and
  • The readings are “instantaneous”, that is, the reading represent the total number of kWh consumed from the time the meter was installed up until “now”, being the instant that the meter reading was made. This is opposed to meters that, for example, record the amount of electricity consumed in a given time period (e.g. half hour) and report that value, along with the start/end date/time for the period.

 

You can read more about the different options for specifying a new meter’s location, various metadata values, and all of the different types of reading(s) that the meter supports in the AMON specification.

For the above call, the AMEE AMON API will include in the return headers (for example):

HTTP/1.1 201 CreatedLocation: /2.0.0/meters/fa7d8626-0fd3-4c61-b82d-5f3b54465b96

 The first line simply states that the meter has been created successfully.

 The Location: header specifies the full URL location of the meter. The final part of the URL (fa7d8626-0fd3-4c61-b82d-5f3b54465b96) is the UUID for the new meter.

#2: Inspecting an Existing Meter

To view the details of an existing meter, send a GET request to the /meters/{meter-UUID} path. For example:

curl -v \   -u username:password \   -H 'Content-Type: application/json' \   -H 'Accept: application/json' \   -X GET \http://metering-api-dev.amee.com/2/meters/fa7d8626-0fd3-4c61-b82d-5f3b54465b96

 For the above call, the AMEE AMON API will return the following data (for example, and after formatting):

 
{
   "meter": {
      "meterId": "fa7d8626-0fd3-4c61-b82d-5f3b54465b96",
      "description": "Test Meter #1234",
      "location": {
         "name": "test_location",
         "longitude": null,
         "latitude": null
      },
      "privacy": "private",
      "readings": [
         {
            "unit": "kWh",
            "resolution": 0,
            "period": "instant",
            "type": "electricityConsumption",
            "accuracy": 0
         }
      ]
   }
}

 This shows the meter’s details, as originally created, as well as some additional default values set for the meter. (For clarity, some additional metadata section items have been omitted from the above response.)

#3: Submitting Measurement Data

To submit measurement data for a meter, send a POST request to the /meters/{meter-UUID}/measurements path. For example, assuming the following JSON data exists in a file called add_data.json:

{
  "measurements": [
      {
         "type": "electricityConsumption",
         "timestamp": "2011-05-12T10:30:00Z",
         "value": 0.5
      }
   ]
}

 then run the command:

curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X POST \-d @add_data.json \http://metering-api-dev.amee.com/2/meters/fa7d8626-0fd3-4c61-b82d-5f3b54465b96/measurements

 For the above call, the AMEE AMON API will include in the return headers (for example):

 HTTP/1.1 201 Created

 It is also possible to submit multiple measurements data items in a single call. For example, assuming the following JSON data exists in a file called add_data.json:

{
   "measurements": [
      {
         "type": "electricityConsumption",
         "timestamp": "2011-05-12T11:00:00Z",
         "value": 1.5
      },
      {
         "type": "electricityConsumption",
         "timestamp": "2011-05-12T11:30:00Z",
         "value": 5.5
      }
   ]
}

 Then the same curl command as above can be run to submit the multiple items.

Timezone Offsets for Measurement Data

When uploading measurement data, it is important that the correct timezone offset be used. The timestamp field (see the AMON specification) must be in RFC 3339 format.

This means that, if your data has been recorded in UTC format, you should use the “+00:00” offset (or simply use “Z” as in the examples above).

However, if your data has been recorded in local time, which changes with daylight savings, then you will need to adjust the offset accordingly. That is, in winter time, when GMT is equal to UTC, use an offset of “+00:00” or “Z”. However, in summer time, when BST time is in force, and the clocks have been put forward one hour, use an offset of “+01:00”.

If your data is recorded in local time, and you do not do this, then all data recorded in BST will be reported incorrectly (i.e. it will be out by one hour).

Please note that the AMEE AMON API will return all measurement data (see the next example) in UTC time. This ensures that all data (correctly uploaded) can be easily compared, as it will always be returned in a single, consistent timezone.

#4: Retrieving Measurement Data

To retrieve measurement data for a meter, send a GET request to the /meters/{meter-UUID}/measurements path. For example:

curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X GET \'http://metering-api-dev.amee.com/2/meters/fa7d8626-0fd3-4c61-b82d-5f3b54465b96/measurements?startDate=2011-05-12T09:30:00Z&endDate=2011-05-12T12:00:00Z'

 Notes:

  1. In the example above, single quotes have been included around the URL. These may be required to escape the ampersand characters in the URL, depending on your system.
  2. Both a “startDate” and an “endDate” must be supplied when retrieving measurement data. These parameters are required to define the start/end date & time boundaries for the measurement data desired to be retrieved.

 For the above call, the AMEE AMON API will return the following data (for example, and after formatting):

 
{
   "measurements": [
      {
         "timestamp": "2011-05-12T10:30:00+0000",
         "name": "electricityConsumption",
         "value": 0.5
      },
      {
         "timestamp": "2011-05-12T11:00:00+0000",
         "name": "electricityConsumption",
         "value": 1.5
      },
      {
         "timestamp": "2011-05-12T11:30:00+0000",
         "name": "electricityConsumption",
         "value": 5.5
      }
   ],
   "status": "OK",
   "version": "2.0.0"
}

#5: Correcting Measurement Data

To re-submit measurement data for a meter in the event that you need to correct data incorrectly uploaded, send a PUT request to the /meters/{meter-UUID}/measurements/{reading-type}/{timestamp} path. For example, assuming the following JSON data exists in a file called update_data.json:

{
   "type": "electricityConsumption",
   "timestamp": "2011-05-12T10:30:00Z",
   "value": 1.0
}

 then run the command:

 curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X PUT \-d @update_data.json \'http://metering-api-dev.amee.com/2/meters/fa7d8626-0fd3-4c61-b82d-5f3b54465b96/measurements/electricityConsumption/2011-05-12T10:30:00Z'

This will overwrite the previously created value of 0.5 (see the example in the previous section) with a new value of 1.0.

Notes:

  • This is a PUT request, not a POST request, because the meter measurement already exists, and this is an AMEE AMON API call to update the measurement (by overwriting the data that already exists).

 For the above call, the AMEE AMON API will include in the return headers (for example):

 HTTP/1.1 200 OK

#6: Associating a Meter with a Property

In order to have meters and their associated measurement data show up in your web application, meters in the data store must be associated with the appropriate property from your web application.

To do this, firstly obtain the property UUID from the your web application. (You may need to create the property in the web application first.)

In the following examples, it is assumed that the property UUID is 79f92169-b491-4700-84e7-5c3dc5dafacf.

To associate a meter with a property, send a PUT request to the /entities/{property-UUID}?append=true path. For example, assuming the following JSON data exists in a file called associate.json:

{
   "entityId": "79f92169-b491-4700-84e7-5c3dc5dafacf",
   "meterIds": [
      "fa7d8626-0fd3-4c61-b82d-5f3b54465b96"
   ]
}

then run the command:

curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X PUT \-d @associate.json \http://metering-api-dev.amee.com/2/entities/79f92169-b491-4700-84e7-5c3dc5dafacf?append=true

 Notes:

  • This is a PUT request, not a POST request, because the entity (the property) already exists, and this is an AMEE AMON API call to update the entity (be associating it with the meter).

 A PUT request of this type will update the property’s associated meters by appending to the list of existing associated meter(s) those specified.

So, to add a second meter to property with UUID 79f92169-b491-4700-84e7-5c3dc5dafacf, assume the following JSON data exists in a file called associate.json:

{
   "entityId": "79f92169-b491-4700-84e7-5c3dc5dafacf",
   "meterIds": [
      "f54ad5f1-2b91-47fc-8982-4efa6ade8354"
   ]
}

 then run the command:

 curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X PUT \-d @associate.json \http://metering-api-dev.amee.com/2/entities/79f92169-b491-4700-84e7-5c3dc5dafacf?append=true

 The command:

 curl -v \-u username:password \-H 'Content-Type: application/json' \-H 'Accept: application/json' \-X GET \http://metering-api-dev.amee.com/2/entities/79f92169-b491-4700-84e7-5c3dc5dafacf

 would now return (for example, after formatting):

{
   "entity": {
      "entityId": "79f92169-b491-4700-84e7-5c3dc5dafacf",
      "meterIds": [
         "fa7d8626-0fd3-4c61-b82d-5f3b54465b96",
         "f54ad5f1-2b91-47fc-8982-4efa6ade8354"
      ],
      "meteringPointIds": []
   },
   "status": "OK",
   "version": "2.0.0"
}

Trouble-Shooting

Error message of:

The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method

or HTTP response code:

UnsupportedMediaType - 415
  • Problem: You have not correctly set the two required HTTP request headers:
    – Accept: application/json
    – Content-Type: application/json

 


 Error message of:

 The request requires user authentication

 or HTTP response code:

 Unauthorized - 401
  • Problem: You have not correctly included your username and password (or your username and password are incorrect) for HTTP basic authentication.

 


 AMEE AMON API response with JSON:

 {"status":"INVALID","validationResult":{"errors":[{"field":"measurement","code":"jsonException"}]

 Error message of:

 The server has not found anything matching the request URI
  •  Problem: The URL used was invalid. Check the URL, in particular, check that it contains the API version e.g. http://hostname/2/path.

Known Issues

An HTTP response code of 404 is returned when querying /meters/{meter-UUID}/measurements, but the meter UUID is known to exists.

  • In this case, the response from the AMEE AMON API is misleading. In fact, the meter does exist, but this response is when the AMEE AMON API call is invalid, because of missing “startDate” and/or “endDate” parameters.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>