1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/amberelectric/config_flow.py
Myles Eftos 412ecacca3
Amberelectric (#56448)
* Add Amber Electric integration

* Linting

* Fixing some type hinting

* Adding docstrings

* Removing files that shouldn't have been changed

* Splitting out test helpers

* Testing the price sensor

* Testing Controlled load and feed in channels

* Refactoring mocks

* switching state for native_value and unit_of_measurement for native_unit_of_measurement

* Fixing docstrings

* Fixing requiremennts_all.txt

* isort fixes

* Fixing pylint errors

* Omitting __init__.py from test coverage

* Add missing config_flow tests

* Adding more sensor tests

* Applying suggested changes to __init.py__

* Refactor coordinator to return the data object with all of the relevent data already setup

* Another coordinator refactor - Better use the dictionary for when we build the sensors

* Removing first function

* Refactoring sensor files to use entity descriptions, remove factory

* Rounding renewable percentage, return icons correctly

* Cleaning up translation strings

* Fixing relative path, removing TODO

* Coordintator tests now accept new (more accurate) fixtures

* Using a description placeholder

* Putting missing translations strings back in

* tighten up the no site error logic - self._site_id should never be None at the point of loading async_step_site

* Removing DEVICE_CLASS, replacing the units with AUD/kWh

* Settings _attr_unique_id

* Removing icon function (it's already the default)

* Apply suggestions from code review

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Adding strings.json

* Tighter wrapping for try/except

* Generating translations

* Removing update_method - not needed as it's being overriden

* Apply suggestions from code review

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Fixing tests

* Add missing description placeholder

* Fix warning

* changing name from update to update_data to match async_update_data

* renaming [async_]update_data => [async_]update_price_data to avoid confusion

* Creating too man renewable sensors

* Override update method

* Coordinator tests use _async_update_data

* Using $/kWh as the units

* Using isinstance instead of __class__ test. Removing a zero len check

* Asserting self._sites in second step

* Linting

* Remove useless tests

Co-authored-by: jan iversen <jancasacondor@gmail.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2021-09-28 00:03:51 -07:00

121 lines
3.8 KiB
Python

"""Config flow for the Amber Electric integration."""
from __future__ import annotations
from typing import Any
import amberelectric
from amberelectric.api import amber_api
from amberelectric.model.site import Site
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_API_TOKEN
from .const import CONF_SITE_ID, CONF_SITE_NAME, CONF_SITE_NMI, DOMAIN
API_URL = "https://app.amber.com.au/developers"
class AmberElectricConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow."""
VERSION = 1
def __init__(self) -> None:
"""Initialize the config flow."""
self._errors: dict[str, str] = {}
self._sites: list[Site] | None = None
self._api_token: str | None = None
def _fetch_sites(self, token: str) -> list[Site] | None:
configuration = amberelectric.Configuration(access_token=token)
api = amber_api.AmberApi.create(configuration)
try:
sites = api.get_sites()
if len(sites) == 0:
self._errors[CONF_API_TOKEN] = "no_site"
return None
return sites
except amberelectric.ApiException as api_exception:
if api_exception.status == 403:
self._errors[CONF_API_TOKEN] = "invalid_api_token"
else:
self._errors[CONF_API_TOKEN] = "unknown_error"
return None
async def async_step_user(self, user_input: dict[str, Any] | None = None):
"""Step when user initializes a integration."""
self._errors = {}
self._sites = None
self._api_token = None
if user_input is not None:
token = user_input[CONF_API_TOKEN]
self._sites = await self.hass.async_add_executor_job(
self._fetch_sites, token
)
if self._sites is not None:
self._api_token = token
return await self.async_step_site()
else:
user_input = {CONF_API_TOKEN: ""}
return self.async_show_form(
step_id="user",
description_placeholders={"api_url": API_URL},
data_schema=vol.Schema(
{
vol.Required(
CONF_API_TOKEN, default=user_input[CONF_API_TOKEN]
): str,
}
),
errors=self._errors,
)
async def async_step_site(self, user_input: dict[str, Any] = None):
"""Step to select site."""
self._errors = {}
assert self._sites is not None
api_token = self._api_token
if user_input is not None:
site_nmi = user_input[CONF_SITE_NMI]
sites = [site for site in self._sites if site.nmi == site_nmi]
site = sites[0]
site_id = site.id
name = user_input.get(CONF_SITE_NAME, site_id)
return self.async_create_entry(
title=name,
data={
CONF_SITE_ID: site_id,
CONF_API_TOKEN: api_token,
CONF_SITE_NMI: site.nmi,
},
)
user_input = {
CONF_API_TOKEN: api_token,
CONF_SITE_NMI: "",
CONF_SITE_NAME: "",
}
return self.async_show_form(
step_id="site",
data_schema=vol.Schema(
{
vol.Required(
CONF_SITE_NMI, default=user_input[CONF_SITE_NMI]
): vol.In([site.nmi for site in self._sites]),
vol.Optional(
CONF_SITE_NAME, default=user_input[CONF_SITE_NAME]
): str,
}
),
errors=self._errors,
)