My power utility company, ComEd offers spot-pricing plans that allow consumers to pay a variable rate based on supply and demand. While this practice has seen some recent controversy it has saved me $400 over the last couple of years.

ComEd provides pricing data so that subscribers can make smart energy consumption decisions. Since they also offer their pricing data via an API, I have Telegraf reading the data on a regular basis and storing it in an InfluxDB 2.0 open-source instance.

Let’s get this done!

I’m using the inputs.http plugin to send a http request, interpret the results, format them correctly, and store them in a bucket.

The ComEd API returns data like this:

[{"millisUTC":"1613877300000","price":"2.3"}]

Starting the configuration, I’ll tell the plugin which URL we want to access to pull the pricing data I want and the interval - because this data is only published every 5 minutes, there’s no need for it to be polled every 30 seconds, the default polling frequency I use for other plugins within this Telegraf instance.

[[inputs.http]]
urls: ["https://hourlypricing.comed.com/api?type=currenthouraverage"]
interval: "5m"

Within the data returned are url and host entries, but I don’t need to store those in the database, so I’ll exclude them:

tagexclude: ["url", "host"]

When using the [[inputs.http]] plugin, the default name will end up being http unless otherwise specified, so I’ve overridden it with a more descriptive name:

name_override: "hour-average"

Since the plugin can handle all sorts of data formats, I’ll tell it to expect JSON:

data_format: "json"

Further, it’s important to tell the plugin what JSON keys to work with. You can easily pick and choose bits within a JSON array to import, ignore, or manipulate.

json_name_key: "price"

Because the response from the API includes a timestamp, I want Telegraf to use that time as the time used when inserting the data. If I omit this, InfluxDB will use the time the data arrives instead, which I don’t want because then the pricing data will be aligned with the time the data was received instead of when the pricing was valid. I’ll use this configuration to tell Telegraf which key contains the time, and what format that time is in:

json_time_key: "millisUTC"
json_time_format: "unix_ms"

One last thing! I need to change the price from a string to a float because of how the data is presented by the ComEd API. To do this, I’m using a Telegraf processor:

[[processors.converter]]
[processors.converter.fields]
float: ["price"]

Putting it all together, here’s the full Telegraf configuration:

[[inputs.http]]
urls: ["https://hourlypricing.comed.com/api?type=5minutefeed"]
tagexclude: ["url", "host"]
name_override: "five-minute"
data_format: "json"
json_name_key: "price"
json_time_key: "millisUTC"
json_time_format: "unix_ms"

[[processors.converter]]
[processors.converter.fields]
float: ["price"]

Very rarely am I able to write a Telegraf configuration that works perfectly on the first try. Fortunately, it’s simple to test a configuration:

$ telegraf --debug --test --config telegraf.conf
2021-02-21T03:49:04Z I! Starting Telegraf 1.17.3
2021-02-21T03:49:04Z D! [agent] Initializing plugins
2021-02-21T03:49:04Z D! [agent] Starting service inputs
> five-minute price=2.4 1613878800000000000
> five-minute price=2.3 1613878500000000000
[...]

And that’s it! The metrics as shown above will now be sent to the InfluxDB instance configured within telegraf.conf.

I’ve created a couple of dashboard cells within InfluxDB 2 that allow me to see historical and current cost at a glance:

In a future post, I’ll explain how you can send alerts and take action on trends observed with this data - this is how you can exploit energy price dips to your advantage automatically!