From 0aedb1df2d241ff400ccdb59c133f4634a414652 Mon Sep 17 00:00:00 2001 From: dotKrad Date: Tue, 17 Dec 2019 23:23:59 -0500 Subject: [PATCH] Used Interface for configuration --- .devcontainer/configuration.yaml | 17 +- .../blueprint/.translations/en.json | 21 -- .../blueprint/.translations/nb.json | 21 -- .../blueprint/.translations/sensor.nb.json | 5 - custom_components/blueprint/__init__.py | 244 ------------------ custom_components/blueprint/binary_sensor.py | 85 ------ custom_components/blueprint/config_flow.py | 83 ------ custom_components/blueprint/const.py | 35 --- custom_components/blueprint/manifest.json | 15 -- custom_components/blueprint/sensor.py | 79 ------ custom_components/blueprint/switch.py | 84 ------ custom_components/fpl/.translations/en.json | 8 +- custom_components/fpl/.translations/nb.json | 21 -- .../fpl/.translations/sensor.nb.json | 5 - custom_components/fpl/__init__.py | 25 ++ custom_components/fpl/config_flow.py | 72 +++--- custom_components/fpl/const.py | 6 +- custom_components/fpl/manifest.json | 2 +- custom_components/fpl/sensor.py | 32 ++- 19 files changed, 105 insertions(+), 755 deletions(-) delete mode 100644 custom_components/blueprint/.translations/en.json delete mode 100644 custom_components/blueprint/.translations/nb.json delete mode 100644 custom_components/blueprint/.translations/sensor.nb.json delete mode 100644 custom_components/blueprint/__init__.py delete mode 100644 custom_components/blueprint/binary_sensor.py delete mode 100644 custom_components/blueprint/config_flow.py delete mode 100644 custom_components/blueprint/const.py delete mode 100644 custom_components/blueprint/manifest.json delete mode 100644 custom_components/blueprint/sensor.py delete mode 100644 custom_components/blueprint/switch.py delete mode 100644 custom_components/fpl/.translations/nb.json delete mode 100644 custom_components/fpl/.translations/sensor.nb.json diff --git a/.devcontainer/configuration.yaml b/.devcontainer/configuration.yaml index adbd88c..8a4c31e 100644 --- a/.devcontainer/configuration.yaml +++ b/.devcontainer/configuration.yaml @@ -2,19 +2,4 @@ default_config: logger: default: error logs: - custom_components.blueprint: debug - - - -blueprint: - username: my_username - password: my_password - binary_sensor: - - enabled: true - name: My custom name - sensor: - - enabled: true - name: My custom name - switch: - - enabled: true - name: My custom name \ No newline at end of file + custom_components.fpl: debug \ No newline at end of file diff --git a/custom_components/blueprint/.translations/en.json b/custom_components/blueprint/.translations/en.json deleted file mode 100644 index c9aeae6..0000000 --- a/custom_components/blueprint/.translations/en.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "config": { - "title": "Blueprint", - "step": { - "user": { - "title": "Blueprint", - "description": "If you need help with the configuration have a look here: https://github.com/custom-components/blueprint", - "data": { - "username": "Username", - "password": "Password" - } - } - }, - "error": { - "auth": "Username/Password is wrong." - }, - "abort": { - "single_instance_allowed": "Only a single configuration of Blueprint is allowed." - } - } -} \ No newline at end of file diff --git a/custom_components/blueprint/.translations/nb.json b/custom_components/blueprint/.translations/nb.json deleted file mode 100644 index 3b47f66..0000000 --- a/custom_components/blueprint/.translations/nb.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "config": { - "title": "Blueprint", - "step": { - "user": { - "title": "Blueprint", - "description": "Hvis du trenger hjep til konfigurasjon ta en titt her: https://github.com/custom-components/blueprint", - "data": { - "username": "Brukernavn", - "password": "Passord" - } - } - }, - "error": { - "auth": "Brukernavn/Passord er feil." - }, - "abort": { - "single_instance_allowed": "Du kan konfigurere Blueprint kun en gang." - } - } -} \ No newline at end of file diff --git a/custom_components/blueprint/.translations/sensor.nb.json b/custom_components/blueprint/.translations/sensor.nb.json deleted file mode 100644 index ed34ceb..0000000 --- a/custom_components/blueprint/.translations/sensor.nb.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "state": { - "Some sample static text.": "Eksempel tekst." - } -} \ No newline at end of file diff --git a/custom_components/blueprint/__init__.py b/custom_components/blueprint/__init__.py deleted file mode 100644 index e281e53..0000000 --- a/custom_components/blueprint/__init__.py +++ /dev/null @@ -1,244 +0,0 @@ -""" -Component to integrate with blueprint. - -For more details about this component, please refer to -https://github.com/custom-components/blueprint -""" -import os -from datetime import timedelta -import logging -import voluptuous as vol -from homeassistant import config_entries -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers import discovery -from homeassistant.util import Throttle - -from sampleclient.client import Client -from integrationhelper.const import CC_STARTUP_VERSION - -from .const import ( - CONF_BINARY_SENSOR, - CONF_ENABLED, - CONF_NAME, - CONF_PASSWORD, - CONF_SENSOR, - CONF_SWITCH, - CONF_USERNAME, - DEFAULT_NAME, - DOMAIN_DATA, - DOMAIN, - ISSUE_URL, - PLATFORMS, - REQUIRED_FILES, - VERSION, -) - -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) - -_LOGGER = logging.getLogger(__name__) - -BINARY_SENSOR_SCHEMA = vol.Schema( - { - vol.Optional(CONF_ENABLED, default=True): cv.boolean, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - } -) - -SENSOR_SCHEMA = vol.Schema( - { - vol.Optional(CONF_ENABLED, default=True): cv.boolean, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - } -) - -SWITCH_SCHEMA = vol.Schema( - { - vol.Optional(CONF_ENABLED, default=True): cv.boolean, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - } -) - -CONFIG_SCHEMA = vol.Schema( - { - DOMAIN: vol.Schema( - { - vol.Optional(CONF_USERNAME): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, - vol.Optional(CONF_BINARY_SENSOR): vol.All( - cv.ensure_list, [BINARY_SENSOR_SCHEMA] - ), - vol.Optional(CONF_SENSOR): vol.All(cv.ensure_list, [SENSOR_SCHEMA]), - vol.Optional(CONF_SWITCH): vol.All(cv.ensure_list, [SWITCH_SCHEMA]), - } - ) - }, - extra=vol.ALLOW_EXTRA, -) - - -async def async_setup(hass, config): - """Set up this component using YAML.""" - if config.get(DOMAIN) is None: - # We get her if the integration is set up using config flow - return True - - # Print startup message - _LOGGER.info( - CC_STARTUP_VERSION.format(name=DOMAIN, version=VERSION, issue_link=ISSUE_URL) - ) - - # Check that all required files are present - file_check = await check_files(hass) - if not file_check: - return False - - # Create DATA dict - hass.data[DOMAIN_DATA] = {} - - # Get "global" configuration. - username = config[DOMAIN].get(CONF_USERNAME) - password = config[DOMAIN].get(CONF_PASSWORD) - - # Configure the client. - client = Client(username, password) - hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client) - - # Load platforms - for platform in PLATFORMS: - # Get platform specific configuration - platform_config = config[DOMAIN].get(platform, {}) - - # If platform is not enabled, skip. - if not platform_config: - continue - - for entry in platform_config: - entry_config = entry - - # If entry is not enabled, skip. - if not entry_config[CONF_ENABLED]: - continue - - hass.async_create_task( - discovery.async_load_platform( - hass, platform, DOMAIN, entry_config, config - ) - ) - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={} - ) - ) - return True - - -async def async_setup_entry(hass, config_entry): - """Set up this integration using UI.""" - conf = hass.data.get(DOMAIN_DATA) - if config_entry.source == config_entries.SOURCE_IMPORT: - if conf is None: - hass.async_create_task( - hass.config_entries.async_remove(config_entry.entry_id) - ) - return False - - # Print startup message - _LOGGER.info( - CC_STARTUP_VERSION.format(name=DOMAIN, version=VERSION, issue_link=ISSUE_URL) - ) - - # Check that all required files are present - file_check = await check_files(hass) - if not file_check: - return False - - # Create DATA dict - hass.data[DOMAIN_DATA] = {} - - # Get "global" configuration. - username = config_entry.data.get(CONF_USERNAME) - password = config_entry.data.get(CONF_PASSWORD) - - # Configure the client. - client = Client(username, password) - hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client) - - # Add binary_sensor - hass.async_add_job( - hass.config_entries.async_forward_entry_setup(config_entry, "binary_sensor") - ) - - # Add sensor - hass.async_add_job( - hass.config_entries.async_forward_entry_setup(config_entry, "sensor") - ) - - # Add switch - hass.async_add_job( - hass.config_entries.async_forward_entry_setup(config_entry, "switch") - ) - - return True - - -class BlueprintData: - """This class handle communication and stores the data.""" - - def __init__(self, hass, client): - """Initialize the class.""" - self.hass = hass - self.client = client - - @Throttle(MIN_TIME_BETWEEN_UPDATES) - async def update_data(self): - """Update data.""" - # This is where the main logic to update platform data goes. - try: - data = self.client.get_data() - self.hass.data[DOMAIN_DATA]["data"] = data - except Exception as error: # pylint: disable=broad-except - _LOGGER.error("Could not update data - %s", error) - - -async def check_files(hass): - """Return bool that indicates if all files are present.""" - # Verify that the user downloaded all files. - base = f"{hass.config.path()}/custom_components/{DOMAIN}/" - missing = [] - for file in REQUIRED_FILES: - fullpath = "{}{}".format(base, file) - if not os.path.exists(fullpath): - missing.append(file) - - if missing: - _LOGGER.critical("The following files are missing: %s", str(missing)) - returnvalue = False - else: - returnvalue = True - - return returnvalue - - -async def async_remove_entry(hass, config_entry): - """Handle removal of an entry.""" - try: - await hass.config_entries.async_forward_entry_unload( - config_entry, "binary_sensor" - ) - _LOGGER.info( - "Successfully removed binary_sensor from the blueprint integration" - ) - except ValueError: - pass - - try: - await hass.config_entries.async_forward_entry_unload(config_entry, "sensor") - _LOGGER.info("Successfully removed sensor from the blueprint integration") - except ValueError: - pass - - try: - await hass.config_entries.async_forward_entry_unload(config_entry, "switch") - _LOGGER.info("Successfully removed switch from the blueprint integration") - except ValueError: - pass diff --git a/custom_components/blueprint/binary_sensor.py b/custom_components/blueprint/binary_sensor.py deleted file mode 100644 index 552995d..0000000 --- a/custom_components/blueprint/binary_sensor.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Binary sensor platform for blueprint.""" -from homeassistant.components.binary_sensor import BinarySensorDevice -from .const import ( - ATTRIBUTION, - BINARY_SENSOR_DEVICE_CLASS, - DEFAULT_NAME, - DOMAIN_DATA, - DOMAIN, -) - - -async def async_setup_platform( - hass, config, async_add_entities, discovery_info=None -): # pylint: disable=unused-argument - """Setup binary_sensor platform.""" - async_add_entities([BlueprintBinarySensor(hass, discovery_info)], True) - - -async def async_setup_entry(hass, config_entry, async_add_devices): - """Setup sensor platform.""" - async_add_devices([BlueprintBinarySensor(hass, {})], True) - - -class BlueprintBinarySensor(BinarySensorDevice): - """blueprint binary_sensor class.""" - - def __init__(self, hass, config): - self.hass = hass - self.attr = {} - self._status = False - self._name = config.get("name", DEFAULT_NAME) - - async def async_update(self): - """Update the binary_sensor.""" - # Send update "signal" to the component - await self.hass.data[DOMAIN_DATA]["client"].update_data() - - # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) - - # Check the data and update the value. - if updated.get("bool_on") is None: - self._status = self._status - else: - self._status = updated.get("bool_on") - - # Set/update attributes - self.attr["attribution"] = ATTRIBUTION - self.attr["time"] = str(updated.get("time")) - self.attr["static"] = updated.get("static") - - @property - def unique_id(self): - """Return a unique ID to use for this binary_sensor.""" - return ( - "0919a0cd-745c-48fd" - ) # Don't had code this, use something from the device/service. - - @property - def device_info(self): - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": self.name, - "manufacturer": "Blueprint", - } - - @property - def name(self): - """Return the name of the binary_sensor.""" - return self._name - - @property - def device_class(self): - """Return the class of this binary_sensor.""" - return BINARY_SENSOR_DEVICE_CLASS - - @property - def is_on(self): - """Return true if the binary_sensor is on.""" - return self._status - - @property - def device_state_attributes(self): - """Return the state attributes.""" - return self.attr diff --git a/custom_components/blueprint/config_flow.py b/custom_components/blueprint/config_flow.py deleted file mode 100644 index 92a0e0e..0000000 --- a/custom_components/blueprint/config_flow.py +++ /dev/null @@ -1,83 +0,0 @@ -"""Adds config flow for Blueprint.""" -from collections import OrderedDict - -import voluptuous as vol -from sampleclient.client import Client -from homeassistant import config_entries - -from .const import DOMAIN - - -@config_entries.HANDLERS.register(DOMAIN) -class BlueprintFlowHandler(config_entries.ConfigFlow): - """Config flow for Blueprint.""" - - VERSION = 1 - CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL - - def __init__(self): - """Initialize.""" - self._errors = {} - - async def async_step_user( - self, user_input={} - ): # pylint: disable=dangerous-default-value - """Handle a flow initialized by the user.""" - self._errors = {} - if self._async_current_entries(): - return self.async_abort(reason="single_instance_allowed") - if self.hass.data.get(DOMAIN): - return self.async_abort(reason="single_instance_allowed") - - if user_input is not None: - valid = await self._test_credentials( - user_input["username"], user_input["password"] - ) - if valid: - return self.async_create_entry(title="", data=user_input) - else: - self._errors["base"] = "auth" - - return await self._show_config_form(user_input) - - return await self._show_config_form(user_input) - - async def _show_config_form(self, user_input): - """Show the configuration form to edit location data.""" - - # Defaults - username = "" - password = "" - - if user_input is not None: - if "username" in user_input: - username = user_input["username"] - if "password" in user_input: - password = user_input["password"] - - data_schema = OrderedDict() - data_schema[vol.Required("username", default=username)] = str - data_schema[vol.Required("password", default=password)] = str - return self.async_show_form( - step_id="user", data_schema=vol.Schema(data_schema), errors=self._errors - ) - - async def async_step_import(self, user_input): # pylint: disable=unused-argument - """Import a config entry. - Special type of import, we're not actually going to store any data. - Instead, we're going to rely on the values that are in config file. - """ - if self._async_current_entries(): - return self.async_abort(reason="single_instance_allowed") - - return self.async_create_entry(title="configuration.yaml", data={}) - - async def _test_credentials(self, username, password): - """Return true if credentials is valid.""" - try: - client = Client(username, password) - client.get_data() - return True - except Exception: # pylint: disable=broad-except - pass - return False diff --git a/custom_components/blueprint/const.py b/custom_components/blueprint/const.py deleted file mode 100644 index 45d6e9c..0000000 --- a/custom_components/blueprint/const.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Constants for blueprint.""" -# Base component constants -DOMAIN = "blueprint" -DOMAIN_DATA = f"{DOMAIN}_data" -VERSION = "0.0.1" -PLATFORMS = ["binary_sensor", "sensor", "switch"] -REQUIRED_FILES = [ - ".translations/en.json", - "binary_sensor.py", - "const.py", - "config_flow.py", - "manifest.json", - "sensor.py", - "switch.py", -] -ISSUE_URL = "https://github.com/custom-components/blueprint/issues" -ATTRIBUTION = "Data from this is provided by blueprint." - -# Icons -ICON = "mdi:format-quote-close" - -# Device classes -BINARY_SENSOR_DEVICE_CLASS = "connectivity" - -# Configuration -CONF_BINARY_SENSOR = "binary_sensor" -CONF_SENSOR = "sensor" -CONF_SWITCH = "switch" -CONF_ENABLED = "enabled" -CONF_NAME = "name" -CONF_USERNAME = "username" -CONF_PASSWORD = "password" - -# Defaults -DEFAULT_NAME = DOMAIN diff --git a/custom_components/blueprint/manifest.json b/custom_components/blueprint/manifest.json deleted file mode 100644 index 767d033..0000000 --- a/custom_components/blueprint/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "domain": "blueprint", - "name": "Blueprint", - "documentation": "https://github.com/custom-components/blueprint", - "dependencies": [], - "config_flow": true, - "codeowners": [ - "@ludeeus" - ], - "requirements": [ - "sampleclient", - "integrationhelper" - ], - "homeassistant": "0.96.0" -} \ No newline at end of file diff --git a/custom_components/blueprint/sensor.py b/custom_components/blueprint/sensor.py deleted file mode 100644 index 5ea9cdd..0000000 --- a/custom_components/blueprint/sensor.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Sensor platform for blueprint.""" -from homeassistant.helpers.entity import Entity -from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON, DOMAIN - - -async def async_setup_platform( - hass, config, async_add_entities, discovery_info=None -): # pylint: disable=unused-argument - """Setup sensor platform.""" - async_add_entities([BlueprintSensor(hass, discovery_info)], True) - - -async def async_setup_entry(hass, config_entry, async_add_devices): - """Setup sensor platform.""" - async_add_devices([BlueprintSensor(hass, {})], True) - - -class BlueprintSensor(Entity): - """blueprint Sensor class.""" - - def __init__(self, hass, config): - self.hass = hass - self.attr = {} - self._state = None - self._name = config.get("name", DEFAULT_NAME) - - async def async_update(self): - """Update the sensor.""" - # Send update "signal" to the component - await self.hass.data[DOMAIN_DATA]["client"].update_data() - - # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) - - # Check the data and update the value. - if updated.get("static") is None: - self._state = self._state - else: - self._state = updated.get("static") - - # Set/update attributes - self.attr["attribution"] = ATTRIBUTION - self.attr["time"] = str(updated.get("time")) - self.attr["none"] = updated.get("none") - - @property - def unique_id(self): - """Return a unique ID to use for this sensor.""" - return ( - "0717a0cd-745c-48fd" - ) # Don't had code this, use something from the device/service. - - @property - def device_info(self): - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": self.name, - "manufacturer": "Blueprint", - } - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def state(self): - """Return the state of the sensor.""" - return self._state - - @property - def icon(self): - """Return the icon of the sensor.""" - return ICON - - @property - def device_state_attributes(self): - """Return the state attributes.""" - return self.attr diff --git a/custom_components/blueprint/switch.py b/custom_components/blueprint/switch.py deleted file mode 100644 index d44c825..0000000 --- a/custom_components/blueprint/switch.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Switch platform for blueprint.""" -from homeassistant.components.switch import SwitchDevice -from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON, DOMAIN - - -async def async_setup_platform( - hass, config, async_add_entities, discovery_info=None -): # pylint: disable=unused-argument - """Setup switch platform.""" - async_add_entities([BlueprintBinarySwitch(hass, discovery_info)], True) - - -async def async_setup_entry(hass, config_entry, async_add_devices): - """Setup sensor platform.""" - async_add_devices([BlueprintBinarySwitch(hass, {})], True) - - -class BlueprintBinarySwitch(SwitchDevice): - """blueprint switch class.""" - - def __init__(self, hass, config): - self.hass = hass - self.attr = {} - self._status = False - self._name = config.get("name", DEFAULT_NAME) - - async def async_update(self): - """Update the switch.""" - # Send update "signal" to the component - await self.hass.data[DOMAIN_DATA]["client"].update_data() - - # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) - - # Check the data and update the value. - self._status = self.hass.data[DOMAIN_DATA]["client"].client.something - - # Set/update attributes - self.attr["attribution"] = ATTRIBUTION - self.attr["time"] = str(updated.get("time")) - self.attr["static"] = updated.get("static") - - async def async_turn_on(self, **kwargs): # pylint: disable=unused-argument - """Turn on the switch.""" - await self.hass.data[DOMAIN_DATA]["client"].client.change_something(True) - - async def async_turn_off(self, **kwargs): # pylint: disable=unused-argument - """Turn off the switch.""" - await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False) - - @property - def unique_id(self): - """Return a unique ID to use for this switch.""" - return ( - "0818a0cd-745c-48fd" - ) # Don't had code this, use something from the device/service. - - @property - def device_info(self): - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": self.name, - "manufacturer": "Blueprint", - } - - @property - def name(self): - """Return the name of the switch.""" - return self._name - - @property - def icon(self): - """Return the icon of this switch.""" - return ICON - - @property - def is_on(self): - """Return true if the switch is on.""" - return self._status - - @property - def device_state_attributes(self): - """Return the state attributes.""" - return self.attr diff --git a/custom_components/fpl/.translations/en.json b/custom_components/fpl/.translations/en.json index 914d6b6..800ba50 100644 --- a/custom_components/fpl/.translations/en.json +++ b/custom_components/fpl/.translations/en.json @@ -1,18 +1,20 @@ { "config": { - "title": "Fpl", + "title": "Florida Power & Light", "step": { "user": { "title": "Florida Power & Light", - "description": "If you need help with the configuration have a look here: https://github.com/custom-components/blueprint", + "description": "If you need help with the configuration have a look here: https://github.com/dotKrad/hass-fpl", "data": { + "name": "Name", "username": "Username", "password": "Password" } } }, "error": { - "auth": "Username/Password is wrong." + "auth": "Username/Password is wrong.", + "name_exists": "Configuration already exists." }, "abort": { "single_instance_allowed": "Only a single configuration of Fpl is allowed." diff --git a/custom_components/fpl/.translations/nb.json b/custom_components/fpl/.translations/nb.json deleted file mode 100644 index 3b47f66..0000000 --- a/custom_components/fpl/.translations/nb.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "config": { - "title": "Blueprint", - "step": { - "user": { - "title": "Blueprint", - "description": "Hvis du trenger hjep til konfigurasjon ta en titt her: https://github.com/custom-components/blueprint", - "data": { - "username": "Brukernavn", - "password": "Passord" - } - } - }, - "error": { - "auth": "Brukernavn/Passord er feil." - }, - "abort": { - "single_instance_allowed": "Du kan konfigurere Blueprint kun en gang." - } - } -} \ No newline at end of file diff --git a/custom_components/fpl/.translations/sensor.nb.json b/custom_components/fpl/.translations/sensor.nb.json deleted file mode 100644 index ed34ceb..0000000 --- a/custom_components/fpl/.translations/sensor.nb.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "state": { - "Some sample static text.": "Eksempel tekst." - } -} \ No newline at end of file diff --git a/custom_components/fpl/__init__.py b/custom_components/fpl/__init__.py index 9107f10..d35fc03 100644 --- a/custom_components/fpl/__init__.py +++ b/custom_components/fpl/__init__.py @@ -1 +1,26 @@ """ FPL Component """ + + +from homeassistant.core import Config, HomeAssistant + +from .config_flow import FplFlowHandler +from .const import DOMAIN + + +async def async_setup(hass: HomeAssistant, config: Config) -> bool: + """Set up configured Fpl.""" + return True + + +async def async_setup_entry(hass, config_entry): + """Set up Fpl as config entry.""" + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(config_entry, "sensor") + ) + return True + + +async def async_unload_entry(hass, config_entry): + """Unload a config entry.""" + await hass.config_entries.async_forward_entry_unload(config_entry, "sensor") + return True diff --git a/custom_components/fpl/config_flow.py b/custom_components/fpl/config_flow.py index a5243d6..c7cecd8 100644 --- a/custom_components/fpl/config_flow.py +++ b/custom_components/fpl/config_flow.py @@ -4,11 +4,20 @@ import voluptuous as vol from .fplapi import FplApi from homeassistant import config_entries import aiohttp -from .const import DOMAIN +from .const import DOMAIN, CONF_USERNAME, CONF_PASSWORD, CONF_NAME +from homeassistant.core import callback -@config_entries.HANDLERS.register(DOMAIN) -class FplFlowHandler(config_entries.ConfigFlow): +@callback +def configured_instances(hass): + """Return a set of configured SimpliSafe instances.""" + entites = [] + for entry in hass.config_entries.async_entries(DOMAIN): + entites.append(f"{entry.data.get(CONF_USERNAME)}") + return set(entites) + + +class FplFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL @@ -22,19 +31,27 @@ class FplFlowHandler(config_entries.ConfigFlow): ): # pylint: disable=dangerous-default-value """Handle a flow initialized by the user.""" self._errors = {} - if self._async_current_entries(): - return self.async_abort(reason="single_instance_allowed") - if self.hass.data.get(DOMAIN): - return self.async_abort(reason="single_instance_allowed") + + # if self._async_current_entries(): + # return self.async_abort(reason="single_instance_allowed") + # if self.hass.data.get(DOMAIN): + # return self.async_abort(reason="single_instance_allowed") if user_input is not None: - valid = await self._test_credentials( - user_input["username"], user_input["password"] - ) - if valid: - return self.async_create_entry(title="", data=user_input) + username = user_input[CONF_USERNAME] + password = user_input[CONF_PASSWORD] + + if username not in configured_instances(self.hass): + valid = await self._test_credentials(username, password) + + if valid: + return self.async_create_entry( + title=user_input[CONF_NAME], data=user_input + ) + else: + self._errors["base"] = "auth" else: - self._errors["base"] = "auth" + self._errors[CONF_NAME] = "name_exists" return await self._show_config_form(user_input) @@ -46,35 +63,28 @@ class FplFlowHandler(config_entries.ConfigFlow): # Defaults username = "" password = "" + name = "Home" if user_input is not None: - if "username" in user_input: - username = user_input["username"] - if "password" in user_input: - password = user_input["password"] + if CONF_USERNAME in user_input: + username = user_input[CONF_USERNAME] + if CONF_PASSWORD in user_input: + password = user_input[CONF_PASSWORD] + if CONF_NAME in user_input: + name = user_input[CONF_NAME] data_schema = OrderedDict() - data_schema[vol.Required("username", default=username)] = str - data_schema[vol.Required("password", default=password)] = str + data_schema[vol.Required(CONF_NAME, default=name)] = str + data_schema[vol.Required(CONF_USERNAME, default=username)] = str + data_schema[vol.Required(CONF_PASSWORD, default=password)] = str + return self.async_show_form( step_id="user", data_schema=vol.Schema(data_schema), errors=self._errors ) - async def async_step_import(self, user_input): # pylint: disable=unused-argument - """Import a config entry. - Special type of import, we're not actually going to store any data. - Instead, we're going to rely on the values that are in config file. - """ - if self._async_current_entries(): - return self.async_abort(reason="single_instance_allowed") - - return self.async_create_entry(title="configuration.yaml", data={}) - async def _test_credentials(self, username, password): """Return true if credentials is valid.""" try: - # client = Client(username, password) - # client.get_data() session = aiohttp.ClientSession() api = FplApi(username, password, True, None, session) await api.login() diff --git a/custom_components/fpl/const.py b/custom_components/fpl/const.py index 5f35a52..1c00d96 100644 --- a/custom_components/fpl/const.py +++ b/custom_components/fpl/const.py @@ -3,7 +3,7 @@ DOMAIN = "fpl" DOMAIN_DATA = f"{DOMAIN}_data" VERSION = "0.0.1" -PLATFORMS = ["binary_sensor", "sensor", "switch"] +PLATFORMS = ["sensor"] REQUIRED_FILES = [ ".translations/en.json", "binary_sensor.py", @@ -14,10 +14,10 @@ REQUIRED_FILES = [ "switch.py", ] ISSUE_URL = "https://github.com/dotKrad/hass-fpl/issues" -ATTRIBUTION = "Data from this is provided by blueprint." +ATTRIBUTION = "Data from this is provided by FPL." # Icons -ICON = "mdi:format-quote-close" +ICON = "mdi:flash" # Device classes BINARY_SENSOR_DEVICE_CLASS = "connectivity" diff --git a/custom_components/fpl/manifest.json b/custom_components/fpl/manifest.json index a81ca8a..6478f5f 100644 --- a/custom_components/fpl/manifest.json +++ b/custom_components/fpl/manifest.json @@ -1,7 +1,7 @@ { "domain": "fpl", "name": "FPL", - "documentation": "https://github.com/custom-components/blueprint", + "documentation": "https://github.com/dotKrad/hass-fpl", "dependencies": [], "config_flow": true, "codeowners": [ diff --git a/custom_components/fpl/sensor.py b/custom_components/fpl/sensor.py index 8b9a0db..1acf304 100644 --- a/custom_components/fpl/sensor.py +++ b/custom_components/fpl/sensor.py @@ -6,6 +6,9 @@ import asyncio from homeassistant.helpers.entity import Entity from homeassistant import util +from homeassistant.const import CONF_NAME, EVENT_CORE_CONFIG_UPDATE +from .const import DOMAIN, ICON + MIN_TIME_BETWEEN_SCANS = timedelta(minutes=1440) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1440) @@ -19,24 +22,47 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices([FplSensor(hass, config)]) +async def async_setup_entry(hass, config_entry, async_add_entities): + async_add_entities([FplSensor(hass, config_entry.data)]) + + class FplSensor(Entity): def __init__(self, hass, config): - print("init") + self._config = config self.username = config.get(const.CONF_USERNAME) self.password = config.get(const.CONF_PASSWORD) self._state = 0 self.loop = hass.loop self.api = None + async def _core_config_updated(self, _event): + """Handle core config updated.""" + print("Core config updated") + # self._init_data() + # if self._unsub_fetch_data: + # self._unsub_fetch_data() + # self._unsub_fetch_data = None + # await self._fetch_data() + + async def async_added_to_hass(self): + await self.async_update() + @property def name(self): - """Returns the name of the sensor.""" - return "fpl" + name = self._config.get(CONF_NAME) + if name is not None: + return f"{DOMAIN.upper()} {name}" + + return DOMAIN @property def state(self): return self._state + @property + def icon(self): + return ICON + @property def state_attributes(self): return {