Add griddy integration (#32591)

* Add griddy integration

* Griddy is a wholesale power provider in Texas

* Supports all four load zones in Texas

* Provides real time power price which is useful for automations to handle demand response

* Update homeassistant/components/griddy/sensor.py

Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io>

* Update homeassistant/components/griddy/config_flow.py

Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io>

* Add ability request updated via entity update service.

* Improve error message about already configured

* Remove DEVICE_CLASS_POWER since we do not have a device class for cost

* remove setdefault that was left from previous refactor

* More detail on data naming

* Bump translation for testing

* git add the config flow tests

* s/PlatformNotReady/ConfigEntryNotReady/

* Review items

* git add the other missing file

* Patch griddypower

* reduce

* adjust target

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
J. Nick Koston 2020-03-10 17:00:30 -05:00 committed by GitHub
parent 21cff003f8
commit 908ae23738
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1012 additions and 0 deletions

View File

@ -140,6 +140,7 @@ homeassistant/components/google_translate/* @awarecan
homeassistant/components/google_travel_time/* @robbiet480
homeassistant/components/gpsd/* @fabaff
homeassistant/components/greeneye_monitor/* @jkeljo
homeassistant/components/griddy/* @bdraco
homeassistant/components/group/* @home-assistant/core
homeassistant/components/growatt_server/* @indykoning
homeassistant/components/gtfs/* @robbiet480

View File

@ -0,0 +1,21 @@
{
"config" : {
"error" : {
"cannot_connect" : "Failed to connect, please try again",
"unknown" : "Unexpected error"
},
"title" : "Griddy",
"step" : {
"user" : {
"description" : "Your Load Zone is in your Griddy account under “Account > Meter > Load Zone.”",
"data" : {
"loadzone" : "Load Zone (Settlement Point)"
},
"title" : "Setup your Griddy Load Zone"
}
},
"abort" : {
"already_configured" : "This Load Zone is already configured"
}
}
}

View File

@ -0,0 +1,96 @@
"""The Griddy Power integration."""
import asyncio
from datetime import timedelta
import logging
from griddypower.async_api import LOAD_ZONES, AsyncGriddy
import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import CONF_LOADZONE, DOMAIN, UPDATE_INTERVAL
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema(
{DOMAIN: vol.Schema({vol.Required(CONF_LOADZONE): vol.In(LOAD_ZONES)})},
extra=vol.ALLOW_EXTRA,
)
PLATFORMS = ["sensor"]
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Griddy Power component."""
hass.data.setdefault(DOMAIN, {})
conf = config.get(DOMAIN)
if not conf:
return True
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={CONF_LOADZONE: conf.get(CONF_LOADZONE)},
)
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up Griddy Power from a config entry."""
entry_data = entry.data
async_griddy = AsyncGriddy(
aiohttp_client.async_get_clientsession(hass),
settlement_point=entry_data[CONF_LOADZONE],
)
async def async_update_data():
"""Fetch data from API endpoint."""
return await async_griddy.async_getnow()
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name="Griddy getnow",
update_method=async_update_data,
update_interval=timedelta(seconds=UPDATE_INTERVAL),
)
await coordinator.async_refresh()
if not coordinator.last_update_success:
raise ConfigEntryNotReady
hass.data[DOMAIN][entry.entry_id] = coordinator
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(entry, component)
for component in PLATFORMS
]
)
)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok

View File

@ -0,0 +1,75 @@
"""Config flow for Griddy Power integration."""
import asyncio
import logging
from aiohttp import ClientError
from griddypower.async_api import LOAD_ZONES, AsyncGriddy
import voluptuous as vol
from homeassistant import config_entries, core, exceptions
from homeassistant.helpers import aiohttp_client
from .const import CONF_LOADZONE
from .const import DOMAIN # pylint:disable=unused-import
_LOGGER = logging.getLogger(__name__)
DATA_SCHEMA = vol.Schema({vol.Required(CONF_LOADZONE): vol.In(LOAD_ZONES)})
async def validate_input(hass: core.HomeAssistant, data):
"""Validate the user input allows us to connect.
Data has the keys from DATA_SCHEMA with values provided by the user.
"""
client_session = aiohttp_client.async_get_clientsession(hass)
try:
await AsyncGriddy(
client_session, settlement_point=data[CONF_LOADZONE]
).async_getnow()
except (asyncio.TimeoutError, ClientError):
raise CannotConnect
# Return info that you want to store in the config entry.
return {"title": f"Load Zone {data[CONF_LOADZONE]}"}
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Griddy Power."""
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}
info = None
if user_input is not None:
try:
info = await validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
if "base" not in errors:
await self.async_set_unique_id(user_input[CONF_LOADZONE])
self._abort_if_unique_id_configured()
return self.async_create_entry(title=info["title"], data=user_input)
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors
)
async def async_step_import(self, user_input):
"""Handle import."""
await self.async_set_unique_id(user_input[CONF_LOADZONE])
self._abort_if_unique_id_configured()
return await self.async_step_user(user_input)
class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""

View File

@ -0,0 +1,7 @@
"""Constants for the Griddy Power integration."""
DOMAIN = "griddy"
UPDATE_INTERVAL = 90
CONF_LOADZONE = "loadzone"

View File

@ -0,0 +1,14 @@
{
"domain": "griddy",
"name": "Griddy Power",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/griddy",
"requirements": ["griddypower==0.1.0"],
"ssdp": [],
"zeroconf": [],
"homekit": {},
"dependencies": [],
"codeowners": [
"@bdraco"
]
}

View File

@ -0,0 +1,76 @@
"""Support for August sensors."""
import logging
from homeassistant.helpers.entity import Entity
from .const import CONF_LOADZONE, DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the August sensors."""
coordinator = hass.data[DOMAIN][config_entry.entry_id]
settlement_point = config_entry.data[CONF_LOADZONE]
async_add_entities([GriddyPriceSensor(settlement_point, coordinator)], True)
class GriddyPriceSensor(Entity):
"""Representation of an August sensor."""
def __init__(self, settlement_point, coordinator):
"""Initialize the sensor."""
self._coordinator = coordinator
self._settlement_point = settlement_point
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return "¢/kWh"
@property
def name(self):
"""Device Name."""
return f"{self._settlement_point} Price Now"
@property
def icon(self):
"""Device Ice."""
return "mdi:currency-usd"
@property
def unique_id(self):
"""Device Uniqueid."""
return f"{self._settlement_point}_price_now"
@property
def available(self):
"""Return True if entity is available."""
return self._coordinator.last_update_success
@property
def state(self):
"""Get the current price."""
return round(float(self._coordinator.data.now.price_cents_kwh), 4)
@property
def should_poll(self):
"""Return False, updates are controlled via coordinator."""
return False
async def async_update(self):
"""Update the entity.
Only used by the generic entity update service.
"""
await self._coordinator.async_request_refresh()
async def async_added_to_hass(self):
"""Subscribe to updates."""
self._coordinator.async_add_listener(self.async_write_ha_state)
async def async_will_remove_from_hass(self):
"""Undo subscription."""
self._coordinator.async_remove_listener(self.async_write_ha_state)

View File

@ -0,0 +1,21 @@
{
"config" : {
"error" : {
"cannot_connect" : "Failed to connect, please try again",
"unknown" : "Unexpected error"
},
"title" : "Griddy",
"step" : {
"user" : {
"description" : "Your Load Zone is in your Griddy account under “Account > Meter > Load Zone.”",
"data" : {
"loadzone" : "Load Zone (Settlement Point)"
},
"title" : "Setup your Griddy Load Zone"
}
},
"abort" : {
"already_configured" : "This Load Zone is already configured"
}
}
}

View File

@ -36,6 +36,7 @@ FLOWS = [
"gios",
"glances",
"gpslogger",
"griddy",
"hangouts",
"heos",
"hisense_aehw4a1",

View File

@ -641,6 +641,9 @@ greeneye_monitor==2.0
# homeassistant.components.greenwave
greenwavereality==0.5.1
# homeassistant.components.griddy
griddypower==0.1.0
# homeassistant.components.growatt_server
growattServer==0.0.1

View File

@ -235,6 +235,9 @@ google-api-python-client==1.6.4
# homeassistant.components.google_pubsub
google-cloud-pubsub==0.39.1
# homeassistant.components.griddy
griddypower==0.1.0
# homeassistant.components.ffmpeg
ha-ffmpeg==2.0

View File

@ -0,0 +1 @@
"""Tests for the Griddy Power integration."""

View File

@ -0,0 +1,54 @@
"""Test the Griddy Power config flow."""
import asyncio
from asynctest import MagicMock, patch
from homeassistant import config_entries, setup
from homeassistant.components.griddy.const import DOMAIN
async def test_form(hass):
"""Test we get the form."""
await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
with patch(
"homeassistant.components.griddy.config_flow.AsyncGriddy.async_getnow",
return_value=MagicMock(),
), patch(
"homeassistant.components.griddy.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.griddy.async_setup_entry", return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"loadzone": "LZ_HOUSTON"},
)
assert result2["type"] == "create_entry"
assert result2["title"] == "Load Zone LZ_HOUSTON"
assert result2["data"] == {"loadzone": "LZ_HOUSTON"}
await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_cannot_connect(hass):
"""Test we handle cannot connect error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.griddy.config_flow.AsyncGriddy.async_getnow",
side_effect=asyncio.TimeoutError,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"loadzone": "LZ_NORTH"},
)
assert result2["type"] == "form"
assert result2["errors"] == {"base": "cannot_connect"}

View File

@ -0,0 +1,39 @@
"""The sensor tests for the griddy platform."""
import json
import os
from asynctest import patch
from griddypower.async_api import GriddyPriceData
from homeassistant.components.griddy import CONF_LOADZONE, DOMAIN
from homeassistant.setup import async_setup_component
from tests.common import load_fixture
async def _load_json_fixture(hass, path):
fixture = await hass.async_add_executor_job(
load_fixture, os.path.join("griddy", path)
)
return json.loads(fixture)
def _mock_get_config():
"""Return a default griddy config."""
return {DOMAIN: {CONF_LOADZONE: "LZ_HOUSTON"}}
async def test_houston_loadzone(hass):
"""Test creation of the houston load zone."""
getnow_json = await _load_json_fixture(hass, "getnow.json")
griddy_price_data = GriddyPriceData(getnow_json)
with patch(
"homeassistant.components.griddy.AsyncGriddy.async_getnow",
return_value=griddy_price_data,
):
assert await async_setup_component(hass, DOMAIN, _mock_get_config())
await hass.async_block_till_done()
sensor_lz_houston_price_now = hass.states.get("sensor.lz_houston_price_now")
assert sensor_lz_houston_price_now.state == "1.269"

600
tests/fixtures/griddy/getnow.json vendored Normal file
View File

@ -0,0 +1,600 @@
{
"now": {
"date": "2020-03-08T18:10:16Z",
"hour_num": "18",
"min_num": "10",
"settlement_point": "LZ_HOUSTON",
"price_type": "lmp",
"price_ckwh": "1.26900000000000000000",
"value_score": "11",
"mean_price_ckwh": "1.429706",
"diff_mean_ckwh": "-0.160706",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.544065",
"price_display": "1.3",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T13:10:16-05:00"
},
"forecast": [
{
"date": "2020-03-08T19:00:00Z",
"hour_num": "19",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.32000000",
"value_score": "12",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.113030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.3",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T14:00:00-05:00"
},
{
"date": "2020-03-08T20:00:00Z",
"hour_num": "20",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.37400000",
"value_score": "12",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.059030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.4",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T15:00:00-05:00"
},
{
"date": "2020-03-08T21:00:00Z",
"hour_num": "21",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.44700000",
"value_score": "13",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.013970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.4",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T16:00:00-05:00"
},
{
"date": "2020-03-08T22:00:00Z",
"hour_num": "22",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.52600000",
"value_score": "13",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.092970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.5",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T17:00:00-05:00"
},
{
"date": "2020-03-08T23:00:00Z",
"hour_num": "23",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "2.05100000",
"value_score": "17",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.617970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "2.1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T18:00:00-05:00"
},
{
"date": "2020-03-09T00:00:00Z",
"hour_num": "0",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "2.07400000",
"value_score": "17",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.640970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "2.1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T19:00:00-05:00"
},
{
"date": "2020-03-09T01:00:00Z",
"hour_num": "1",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.94400000",
"value_score": "16",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.510970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.9",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T20:00:00-05:00"
},
{
"date": "2020-03-09T02:00:00Z",
"hour_num": "2",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.57500000",
"value_score": "14",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.141970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.6",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T21:00:00-05:00"
},
{
"date": "2020-03-09T03:00:00Z",
"hour_num": "3",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.23700000",
"value_score": "11",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.196030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T22:00:00-05:00"
},
{
"date": "2020-03-09T04:00:00Z",
"hour_num": "4",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.96200000",
"value_score": "9",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.471030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-08T23:00:00-05:00"
},
{
"date": "2020-03-09T05:00:00Z",
"hour_num": "5",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.80000000",
"value_score": "8",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.633030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.8",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T00:00:00-05:00"
},
{
"date": "2020-03-09T06:00:00Z",
"hour_num": "6",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.70000000",
"value_score": "7",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.733030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.7",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T01:00:00-05:00"
},
{
"date": "2020-03-09T07:00:00Z",
"hour_num": "7",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.70000000",
"value_score": "7",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.733030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.7",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T02:00:00-05:00"
},
{
"date": "2020-03-09T08:00:00Z",
"hour_num": "8",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.70000000",
"value_score": "7",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.733030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.7",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T03:00:00-05:00"
},
{
"date": "2020-03-09T09:00:00Z",
"hour_num": "9",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.70000000",
"value_score": "7",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.733030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.7",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T04:00:00-05:00"
},
{
"date": "2020-03-09T10:00:00Z",
"hour_num": "10",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "0.90000000",
"value_score": "8",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.533030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "0.9",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T05:00:00-05:00"
},
{
"date": "2020-03-09T11:00:00Z",
"hour_num": "11",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.00000000",
"value_score": "9",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.433030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T06:00:00-05:00"
},
{
"date": "2020-03-09T12:00:00Z",
"hour_num": "12",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.10000000",
"value_score": "10",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.333030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T07:00:00-05:00"
},
{
"date": "2020-03-09T13:00:00Z",
"hour_num": "13",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.10000000",
"value_score": "10",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.333030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T08:00:00-05:00"
},
{
"date": "2020-03-09T14:00:00Z",
"hour_num": "14",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.20000000",
"value_score": "11",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.233030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T09:00:00-05:00"
},
{
"date": "2020-03-09T15:00:00Z",
"hour_num": "15",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.20000000",
"value_score": "11",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.233030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T10:00:00-05:00"
},
{
"date": "2020-03-09T16:00:00Z",
"hour_num": "16",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.30000000",
"value_score": "11",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.133030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.3",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T11:00:00-05:00"
},
{
"date": "2020-03-09T17:00:00Z",
"hour_num": "17",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.40000000",
"value_score": "12",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.033030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.4",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T12:00:00-05:00"
},
{
"date": "2020-03-09T18:00:00Z",
"hour_num": "18",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.50000000",
"value_score": "13",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.066970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.5",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T13:00:00-05:00"
},
{
"date": "2020-03-09T19:00:00Z",
"hour_num": "19",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.60000000",
"value_score": "14",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.166970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.6",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T14:00:00-05:00"
},
{
"date": "2020-03-09T20:00:00Z",
"hour_num": "20",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.60000000",
"value_score": "14",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.166970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.6",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T15:00:00-05:00"
},
{
"date": "2020-03-09T21:00:00Z",
"hour_num": "21",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.60000000",
"value_score": "14",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.166970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.6",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T16:00:00-05:00"
},
{
"date": "2020-03-09T22:00:00Z",
"hour_num": "22",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "2.10000000",
"value_score": "18",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.666970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "2.1",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T17:00:00-05:00"
},
{
"date": "2020-03-09T23:00:00Z",
"hour_num": "23",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "3.20000000",
"value_score": "27",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "1.766970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "3.2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T18:00:00-05:00"
},
{
"date": "2020-03-10T00:00:00Z",
"hour_num": "0",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "2.40000000",
"value_score": "20",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.966970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "2.4",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T19:00:00-05:00"
},
{
"date": "2020-03-10T01:00:00Z",
"hour_num": "1",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "2.00000000",
"value_score": "17",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.566970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T20:00:00-05:00"
},
{
"date": "2020-03-10T02:00:00Z",
"hour_num": "2",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.70000000",
"value_score": "15",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "0.266970",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.7",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T21:00:00-05:00"
},
{
"date": "2020-03-10T03:00:00Z",
"hour_num": "3",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.40000000",
"value_score": "12",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.033030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.4",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T22:00:00-05:00"
},
{
"date": "2020-03-10T04:00:00Z",
"hour_num": "4",
"min_num": "0",
"settlement_point": "LZ_HOUSTON",
"price_type": "dam",
"price_ckwh": "1.20000000",
"value_score": "11",
"mean_price_ckwh": "1.433030",
"diff_mean_ckwh": "-0.233030",
"high_ckwh": "3.200000",
"low_ckwh": "0.700000",
"std_dev_ckwh": "0.552149",
"price_display": "1.2",
"price_display_sign": "¢",
"date_local_tz": "2020-03-09T23:00:00-05:00"
}
],
"seconds_until_refresh": "26"
}