From 51573f42808a75d9d79f8c420e653bf73e1e0f04 Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Mon, 30 May 2022 01:27:16 +0200 Subject: [PATCH 1/3] first pass one options handler --- .devcontainer/configuration.yaml | 3 +- custom_components/nordpool/__init__.py | 10 +- custom_components/nordpool/aio_price.py | 14 +- custom_components/nordpool/config_flow.py | 182 +++++++++++++++--- .../nordpool/translations/en.json | 20 +- .../nordpool/translations/nb.json | 20 +- 6 files changed, 206 insertions(+), 43 deletions(-) diff --git a/.devcontainer/configuration.yaml b/.devcontainer/configuration.yaml index 46b5f39..4dcdc56 100644 --- a/.devcontainer/configuration.yaml +++ b/.devcontainer/configuration.yaml @@ -1,9 +1,10 @@ default_config: logger: - default: info + default: warning logs: custom_components.nordpool: debug + custom_components.nordpool.config_flow: debug # If you need to debug uncommment the line below (doc: https://www.home-assistant.io/integrations/debugpy/) # debugpy: diff --git a/custom_components/nordpool/__init__.py b/custom_components/nordpool/__init__.py index 694ca9a..0c3528b 100644 --- a/custom_components/nordpool/__init__.py +++ b/custom_components/nordpool/__init__.py @@ -3,6 +3,7 @@ from datetime import datetime, timedelta from functools import partial from random import randint +from types import MappingProxyType import voluptuous as vol from homeassistant.config_entries import ConfigEntry @@ -176,12 +177,17 @@ async def async_setup(hass: HomeAssistant, config: Config) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up nordpool as config entry.""" + # If any options is passed they should override default config. + d = dict(entry.data) + d.update(dict(entry.options)) + # So many broken rules :P + entry.data = MappingProxyType(d) + res = await _dry_setup(hass, entry.data) hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "sensor") ) - - # entry.add_update_listener(async_reload_entry) + entry.add_update_listener(async_reload_entry) return res diff --git a/custom_components/nordpool/aio_price.py b/custom_components/nordpool/aio_price.py index f79e4f5..1cb854e 100644 --- a/custom_components/nordpool/aio_price.py +++ b/custom_components/nordpool/aio_price.py @@ -154,7 +154,7 @@ async def _io(self, url, **kwargs): return await resp.json() async def _fetch_json(self, data_type, end_date=None, areas=None): - """ Fetch JSON from API """ + """Fetch JSON from API""" # If end_date isn't set, default to tomorrow if end_date is None: end_date = date.today() + timedelta(days=1) @@ -251,27 +251,27 @@ async def fetch(self, data_type, end_date=None, areas=[]): return join_result_for_correct_time(raw, end_date) async def hourly(self, end_date=None, areas=[]): - """ Helper to fetch hourly data, see Prices.fetch() """ + """Helper to fetch hourly data, see Prices.fetch()""" return await self.fetch(self.HOURLY, end_date, areas) async def daily(self, end_date=None, areas=[]): - """ Helper to fetch daily data, see Prices.fetch() """ + """Helper to fetch daily data, see Prices.fetch()""" return await self.fetch(self.DAILY, end_date, areas) async def weekly(self, end_date=None, areas=[]): - """ Helper to fetch weekly data, see Prices.fetch() """ + """Helper to fetch weekly data, see Prices.fetch()""" return await self.fetch(self.WEEKLY, end_date, areas) async def monthly(self, end_date=None, areas=[]): - """ Helper to fetch monthly data, see Prices.fetch() """ + """Helper to fetch monthly data, see Prices.fetch()""" return await self.fetch(self.MONTHLY, end_date, areas) async def yearly(self, end_date=None, areas=[]): - """ Helper to fetch yearly data, see Prices.fetch() """ + """Helper to fetch yearly data, see Prices.fetch()""" return await self.fetch(self.YEARLY, end_date, areas) def _conv_to_float(self, s): - """ Convert numbers to float. Return infinity, if conversion fails. """ + """Convert numbers to float. Return infinity, if conversion fails.""" try: return float(s.replace(",", ".").replace(" ", "")) except ValueError: diff --git a/custom_components/nordpool/config_flow.py b/custom_components/nordpool/config_flow.py index 1601c13..7cdef6a 100644 --- a/custom_components/nordpool/config_flow.py +++ b/custom_components/nordpool/config_flow.py @@ -2,8 +2,12 @@ import logging import re +from copy import deepcopy +from types import MappingProxyType + import voluptuous as vol from homeassistant import config_entries +from homeassistant.core import callback from homeassistant.helpers.template import is_template_string, Template from . import DOMAIN @@ -12,10 +16,60 @@ regions = sorted(list(_REGIONS.keys())) currencys = sorted(list(set(v[0] for k, v in _REGIONS.items()))) price_types = sorted(list(_PRICE_IN.keys())) + +placeholders = { + "region": regions, + "currency": currencys, + "price_type": price_types, + "additional_costs": "{{0.0|float}}", +} + _LOGGER = logging.getLogger(__name__) +data_schema = { + vol.Required("region", default=None): vol.In(regions), + vol.Optional("currency", default=""): vol.In(currencys), + vol.Optional("VAT", default=True): bool, + vol.Optional("precision", default=3): vol.Coerce(int), + vol.Optional("low_price_cutoff", default=1.0): vol.Coerce(float), + vol.Optional("price_in_cents", default=False): bool, + vol.Optional("price_type", default="kWh"): vol.In(price_types), + vol.Optional("additional_costs", default=""): str, +} + + +class Base: + async def _valid_template(self, user_template): + try: + _LOGGER.debug(user_template) + ut = Template(user_template, self.hass).async_render() + if isinstance(ut, float): + return True + else: + return False + except Exception as e: + _LOGGER.error(e) + pass + return False + + async def check_settings(self, user_input): + template_ok = False + if user_input is not None: + if user_input["additional_costs"] in (None, ""): + user_input["additional_costs"] = DEFAULT_TEMPLATE + else: + # Lets try to remove the most common mistakes, this will still fail if the template + # was writte in notepad or something like that.. + user_input["additional_costs"] = re.sub( + r"\s{2,}", "", user_input["additional_costs"] + ) + + template_ok = await self._valid_template(user_input["additional_costs"]) + + return template_ok, user_input -class NordpoolFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): + +class NordpoolFlowHandler(Base, config_entries.ConfigFlow, domain=DOMAIN): """Config flow for Nordpool.""" VERSION = 1 @@ -25,6 +79,36 @@ def __init__(self): """Initialize.""" self._errors = {} + # async def async_step_user( + # self, user_input=None + # ): # pylint: disable=dangerous-default-value + # """Handle a flow initialized by the user.""" + # self._errors = {} + + # if user_input is not None: + # template_ok = False + # if user_input["additional_costs"] in (None, ""): + # user_input["additional_costs"] = DEFAULT_TEMPLATE + # else: + # # Lets try to remove the most common mistakes, this will still fail if the template + # # was writte in notepad or something like that.. + # user_input["additional_costs"] = re.sub( + # r"\s{2,}", "", user_input["additional_costs"] + # ) + + # template_ok = await self._valid_template(user_input["additional_costs"]) + # if template_ok: + # return self.async_create_entry(title=DOMAIN, data=user_input) + # else: + # self._errors["base"] = "invalid_template" + + # return self.async_show_form( + # step_id="user", + # data_schema=vol.Schema(data_schema), + # description_placeholders=placeholders, + # errors=self._errors, + # ) + async def async_step_user( self, user_input=None ): # pylint: disable=dangerous-default-value @@ -32,40 +116,12 @@ async def async_step_user( self._errors = {} if user_input is not None: - template_ok = False - if user_input["additional_costs"] in (None, ""): - user_input["additional_costs"] = DEFAULT_TEMPLATE - else: - # Lets try to remove the most common mistakes, this will still fail if the template - # was writte in notepad or something like that.. - user_input["additional_costs"] = re.sub( - r"\s{2,}", "", user_input["additional_costs"] - ) - - template_ok = await self._valid_template(user_input["additional_costs"]) + template_ok, user_input = await self.check_settings(user_input) if template_ok: - return self.async_create_entry(title="Nordpool", data=user_input) + return self.async_create_entry(title=DOMAIN, data=user_input) else: self._errors["base"] = "invalid_template" - data_schema = { - vol.Required("region", default=None): vol.In(regions), - vol.Optional("currency", default=""): vol.In(currencys), - vol.Optional("VAT", default=True): bool, - vol.Optional("precision", default=3): vol.Coerce(int), - vol.Optional("low_price_cutoff", default=1.0): vol.Coerce(float), - vol.Optional("price_in_cents", default=False): bool, - vol.Optional("price_type", default="kWh"): vol.In(price_types), - vol.Optional("additional_costs", default=""): str, - } - - placeholders = { - "region": regions, - "currency": currencys, - "price_type": price_types, - "additional_costs": "{{0.0|float}}", - } - return self.async_show_form( step_id="user", data_schema=vol.Schema(data_schema), @@ -92,3 +148,67 @@ async def async_step_import(self, user_input): # pylint: disable=unused-argumen Instead, we're going to rely on the values that are in config file. """ return self.async_create_entry(title="configuration.yaml", data={}) + + @staticmethod + @callback + def async_get_options_flow(config_entry): + return NordpoolOptionsFlowHandler(config_entry) + + +class NordpoolOptionsFlowHandler(Base, config_entries.OptionsFlow): + """Handles the options for the component""" + + def __init__(self, config_entry) -> None: + self.config_entry = config_entry + self.options = dict(config_entry.data) # should be options + # self.data = config_entries.data + + async def async_step_init(self, user_input=None): # pylint: disable=unused-argument + """Manage the options.""" + return await self.async_step_user(user_input=user_input) + + async def async_step_edit(self, user_input=None): # pylint: disable=unused-argument + """Manage the options.""" + return await self.async_step_user(user_input=user_input) + + async def async_step_user(self, user_input=None): + """Handle a flow initialized by the user.""" + if user_input is not None: + template_ok, user_input = await self.check_settings(user_input) + if template_ok: + return self.async_create_entry(title=DOMAIN, data=user_input) + else: + self._errors["base"] = "invalid_template" + + self.options.update(user_input) + return self.async_create_entry(title=DOMAIN, data=self.options) + + data_schema2 = { + vol.Required("region", default=self.options.get("region")): vol.In(regions), + vol.Optional("currency", default=self.options.get("currency")): vol.In( + currencys + ), + vol.Optional("VAT", default=self.options.get("VAT")): bool, + vol.Optional( + "precision", default=self.options.get("precision") + ): vol.Coerce(int), + vol.Optional( + "low_price_cutoff", default=self.options.get("low_price_cutoff") + ): vol.Coerce(float), + vol.Optional( + "price_in_cents", default=self.options.get("price_in_cents") + ): bool, + vol.Optional("price_type", default=self.options.get("price_type")): vol.In( + price_types + ), + vol.Optional( + "additional_costs", default=self.options.get("additional_costs") + ): str, + } + + return self.async_show_form( + step_id="edit", + data_schema=vol.Schema(ds2), + description_placeholders=placeholders, + errors={}, + ) diff --git a/custom_components/nordpool/translations/en.json b/custom_components/nordpool/translations/en.json index 414301d..ac1cffe 100644 --- a/custom_components/nordpool/translations/en.json +++ b/custom_components/nordpool/translations/en.json @@ -7,7 +7,7 @@ "description": "Setup a Nordpool sensor", "data": { "region": "Region", - "currency": "NOK", + "currency": "currency", "VAT": "Include VAT", "precision": "How many decimals to show", "low_price_cutoff": "low price cut off", @@ -21,5 +21,23 @@ "name_exists": "Name already exists", "invalid_template": "The template is invalid, check https://github.com/custom-components/nordpool" } + }, + "options": { + "step": { + "edit": { + "title": "Nordpool Sensor", + "description": "Edit a Nordpool sensor", + "data": { + "region": "Region", + "currency": "currency", + "VAT": "Include VAT", + "precision": "How many decimals to show", + "low_price_cutoff": "low price cut off", + "price_in_cents": "Price in Cents", + "price_type": "Price in format", + "additional_costs": "Template for additional costs" + } + } + } } } \ No newline at end of file diff --git a/custom_components/nordpool/translations/nb.json b/custom_components/nordpool/translations/nb.json index 2fd31fe..3bc1969 100644 --- a/custom_components/nordpool/translations/nb.json +++ b/custom_components/nordpool/translations/nb.json @@ -21,5 +21,23 @@ "name_exists": "Navnet eksisterer allerede", "invalid_template": "Malen inneholder feil, se https://github.com/custom-components/nordpool" } + }, + "options": { + "step": { + "edit": { + "title": "Nordpool Sensor", + "description": "Endre en Nordpool sensor", + "data": { + "region": "Område", + "currency": "valuta", + "VAT": "Inkluder moms", + "precision": "Antall desimaler", + "low_price_cutoff": "Lav pris", + "price_in_cents": "Pris i øre", + "price_type": "Pristype", + "additional_costs": "Mal for ekstra kostnader" + } + } + } } -} +} \ No newline at end of file From 624345edd23e441f54cba5bce00f0ec1e04840e4 Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Mon, 30 May 2022 22:04:52 +0200 Subject: [PATCH 2/3] Remove yaml support --- .devcontainer/configuration.yaml | 5 + custom_components/nordpool/__init__.py | 7 +- custom_components/nordpool/config_flow.py | 122 ++++++++-------------- custom_components/nordpool/sensor.py | 42 ++++---- 4 files changed, 71 insertions(+), 105 deletions(-) diff --git a/.devcontainer/configuration.yaml b/.devcontainer/configuration.yaml index 4dcdc56..de54efb 100644 --- a/.devcontainer/configuration.yaml +++ b/.devcontainer/configuration.yaml @@ -8,3 +8,8 @@ logger: # If you need to debug uncommment the line below (doc: https://www.home-assistant.io/integrations/debugpy/) # debugpy: + + +sensor: + - platform: nordpool + region: "Kr.sand" \ No newline at end of file diff --git a/custom_components/nordpool/__init__.py b/custom_components/nordpool/__init__.py index 0c3528b..aa7345a 100644 --- a/custom_components/nordpool/__init__.py +++ b/custom_components/nordpool/__init__.py @@ -6,6 +6,7 @@ from types import MappingProxyType import voluptuous as vol +from homeassistant import config_entries from homeassistant.config_entries import ConfigEntry from homeassistant.core import Config, HomeAssistant from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -114,7 +115,7 @@ async def tomorrow(self, area: str, currency: str): async def _dry_setup(hass: HomeAssistant, config: Config) -> bool: - """Set up using yaml config file.""" + """Helper""" if DOMAIN not in hass.data: api = NordpoolData(hass) @@ -171,8 +172,8 @@ async def new_data_cb(n): async def async_setup(hass: HomeAssistant, config: Config) -> bool: - """Set up using yaml config file.""" - return await _dry_setup(hass, config) + """Setup using yaml isnt supported.""" + return True async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/custom_components/nordpool/config_flow.py b/custom_components/nordpool/config_flow.py index 7cdef6a..277b649 100644 --- a/custom_components/nordpool/config_flow.py +++ b/custom_components/nordpool/config_flow.py @@ -2,13 +2,12 @@ import logging import re -from copy import deepcopy -from types import MappingProxyType +from typing import Optional import voluptuous as vol from homeassistant import config_entries from homeassistant.core import callback -from homeassistant.helpers.template import is_template_string, Template +from homeassistant.helpers.template import Template from . import DOMAIN from .sensor import _PRICE_IN, _REGIONS, DEFAULT_TEMPLATE @@ -26,19 +25,36 @@ _LOGGER = logging.getLogger(__name__) -data_schema = { - vol.Required("region", default=None): vol.In(regions), - vol.Optional("currency", default=""): vol.In(currencys), - vol.Optional("VAT", default=True): bool, - vol.Optional("precision", default=3): vol.Coerce(int), - vol.Optional("low_price_cutoff", default=1.0): vol.Coerce(float), - vol.Optional("price_in_cents", default=False): bool, - vol.Optional("price_type", default="kWh"): vol.In(price_types), - vol.Optional("additional_costs", default=""): str, -} + +def get_schema(existing_config: Optional[dict] = None) -> dict: + """Helper to get schema with editable default""" + + ec = existing_config + + if ec is None: + ec = {} + + data_schema = { + vol.Required("region", default=ec.get("region", None)): vol.In(regions), + vol.Optional("currency", default=ec.get("currency", "")): vol.In(currencys), + vol.Optional("VAT", default=ec.get("VAT", True)): bool, + vol.Optional("precision", default=ec.get("precision", 3)): vol.Coerce(int), + vol.Optional( + "low_price_cutoff", default=ec.get("low_price_cutoff", 1.0) + ): vol.Coerce(float), + vol.Optional("price_in_cents", default=ec.get("price_in_cents", False)): bool, + vol.Optional("price_type", default=ec.get("price_type", "kWh")): vol.In( + price_types + ), + vol.Optional("additional_costs", default=ec.get("additional_costs", "")): str, + } + + return data_schema class Base: + """Simple helper""" + async def _valid_template(self, user_template): try: _LOGGER.debug(user_template) @@ -49,7 +65,7 @@ async def _valid_template(self, user_template): return False except Exception as e: _LOGGER.error(e) - pass + return False async def check_settings(self, user_input): @@ -79,36 +95,6 @@ def __init__(self): """Initialize.""" self._errors = {} - # async def async_step_user( - # self, user_input=None - # ): # pylint: disable=dangerous-default-value - # """Handle a flow initialized by the user.""" - # self._errors = {} - - # if user_input is not None: - # template_ok = False - # if user_input["additional_costs"] in (None, ""): - # user_input["additional_costs"] = DEFAULT_TEMPLATE - # else: - # # Lets try to remove the most common mistakes, this will still fail if the template - # # was writte in notepad or something like that.. - # user_input["additional_costs"] = re.sub( - # r"\s{2,}", "", user_input["additional_costs"] - # ) - - # template_ok = await self._valid_template(user_input["additional_costs"]) - # if template_ok: - # return self.async_create_entry(title=DOMAIN, data=user_input) - # else: - # self._errors["base"] = "invalid_template" - - # return self.async_show_form( - # step_id="user", - # data_schema=vol.Schema(data_schema), - # description_placeholders=placeholders, - # errors=self._errors, - # ) - async def async_step_user( self, user_input=None ): # pylint: disable=dangerous-default-value @@ -122,6 +108,8 @@ async def async_step_user( else: self._errors["base"] = "invalid_template" + data_schema = get_schema(user_input) + return self.async_show_form( step_id="user", data_schema=vol.Schema(data_schema), @@ -129,19 +117,6 @@ async def async_step_user( errors=self._errors, ) - async def _valid_template(self, user_template): - try: - _LOGGER.debug(user_template) - ut = Template(user_template, self.hass).async_render() - if isinstance(ut, float): - return True - else: - return False - except Exception as e: - _LOGGER.error(e) - pass - return False - 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. @@ -152,6 +127,7 @@ async def async_step_import(self, user_input): # pylint: disable=unused-argumen @staticmethod @callback def async_get_options_flow(config_entry): + """Get the Options handler""" return NordpoolOptionsFlowHandler(config_entry) @@ -160,8 +136,12 @@ class NordpoolOptionsFlowHandler(Base, config_entries.OptionsFlow): def __init__(self, config_entry) -> None: self.config_entry = config_entry - self.options = dict(config_entry.data) # should be options + # We dont really care about the options, this component allows all + # settings to be edit after the sensor is created. + # For this to work we need to have a stable entity id. + self.options = dict(config_entry.data) # self.data = config_entries.data + self._errors = {} async def async_step_init(self, user_input=None): # pylint: disable=unused-argument """Manage the options.""" @@ -183,32 +163,12 @@ async def async_step_user(self, user_input=None): self.options.update(user_input) return self.async_create_entry(title=DOMAIN, data=self.options) - data_schema2 = { - vol.Required("region", default=self.options.get("region")): vol.In(regions), - vol.Optional("currency", default=self.options.get("currency")): vol.In( - currencys - ), - vol.Optional("VAT", default=self.options.get("VAT")): bool, - vol.Optional( - "precision", default=self.options.get("precision") - ): vol.Coerce(int), - vol.Optional( - "low_price_cutoff", default=self.options.get("low_price_cutoff") - ): vol.Coerce(float), - vol.Optional( - "price_in_cents", default=self.options.get("price_in_cents") - ): bool, - vol.Optional("price_type", default=self.options.get("price_type")): vol.In( - price_types - ), - vol.Optional( - "additional_costs", default=self.options.get("additional_costs") - ): str, - } + # Get the current settings and use them as default. + ds = get_schema(self.options) return self.async_show_form( step_id="edit", - data_schema=vol.Schema(ds2), + data_schema=vol.Schema(ds), description_placeholders=placeholders, errors={}, ) diff --git a/custom_components/nordpool/sensor.py b/custom_components/nordpool/sensor.py index 6bc8f26..9a944cd 100644 --- a/custom_components/nordpool/sensor.py +++ b/custom_components/nordpool/sensor.py @@ -1,9 +1,11 @@ +from enum import unique import logging import math from datetime import datetime from operator import itemgetter from statistics import mean - +import homeassistant.util.uuid as uuid_util +from homeassistant.helpers.entity import async_generate_entity_id import homeassistant.helpers.config_validation as cv import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA @@ -56,6 +58,7 @@ DEFAULT_CURRENCY = "NOK" DEFAULT_REGION = "Kr.sand" DEFAULT_NAME = "Elspot" +ENTITY_ID_FORMAT = DOMAIN + ".{}" DEFAULT_TEMPLATE = "{{0.0|float}}" @@ -79,8 +82,8 @@ ) -def _dry_setup(hass, config, add_devices, discovery_info=None): - """Setup the damn platform using yaml.""" +def _dry_setup(hass, config, add_devices, discovery_info=None, unique_id=None): + """Setup the platform""" _LOGGER.debug("Dumping config %r", config) _LOGGER.debug("timezone set in ha %r", hass.config.time_zone) region = config.get(CONF_REGION) @@ -93,6 +96,7 @@ def _dry_setup(hass, config, add_devices, discovery_info=None): use_cents = config.get("price_in_cents") ad_template = config.get("additional_costs") api = hass.data[DOMAIN] + sensor = NordpoolSensor( friendly_name, region, @@ -105,24 +109,26 @@ def _dry_setup(hass, config, add_devices, discovery_info=None): api, ad_template, hass, + unique_id, ) add_devices([sensor]) async def async_setup_platform(hass, config, add_devices, discovery_info=None) -> None: - _dry_setup(hass, config, add_devices) return True async def async_setup_entry(hass, config_entry, async_add_devices): """Setup sensor platform for the ui""" config = config_entry.data - _dry_setup(hass, config, async_add_devices) + _dry_setup(hass, config, async_add_devices, unique_id=config_entry.entry_id) return True class NordpoolSensor(Entity): + """Sensor""" + def __init__( self, friendly_name, @@ -136,9 +142,8 @@ def __init__( api, ad_template, hass, + unique_id, ) -> None: - # friendly_name is ignored as it never worked. - # rename the sensor in the ui if you dont like the name. self._area = area self._currency = currency or _REGIONS[area][0] self._price_type = price_type @@ -148,6 +153,8 @@ def __init__( self._api = api self._ad_template = ad_template self._hass = hass + self._attr_unique_id = unique_id + self._unique_id = unique_id if vat is True: self._vat = _REGIONS[area][2] @@ -188,7 +195,7 @@ def __init__( @property def name(self) -> str: - return self.unique_id + return "nordpool" @property def should_poll(self): @@ -213,17 +220,8 @@ def unit_of_measurement(self) -> str: return "%s/%s" % (_currency, self._price_type) @property - def unique_id(self): - name = "nordpool_%s_%s_%s_%s_%s_%s" % ( - self._price_type, - self._area, - self._currency, - self._precision, - self._low_price_cutoff, - self._vat, - ) - name = name.lower().replace(".", "") - return name + def unique_id(self) -> None: + return self._unique_id @property def device_info(self): @@ -321,7 +319,7 @@ def _update(self, data) -> None: @property def current_price(self) -> float: res = self._calc_price() - # _LOGGER.debug("Current hours price for %s is %s", self.name, res) + _LOGGER.debug("Current hours price for %s is %s", self.name, res) return res def _someday(self, data) -> list: @@ -384,8 +382,10 @@ def extra_state_attributes(self) -> dict: "currency": self._currency, "country": _REGIONS[self._area][1], "region": self._area, - "low price": self.low_price, + "low_price": self.low_price, "tomorrow_valid": self.tomorrow_valid, + "precision": self._precision, + "unique_id": self.unique_id, "today": self.today, "tomorrow": self.tomorrow, "raw_today": self.raw_today, From 425bff5cf0b00bb94af624412ec177d9841ebb14 Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Mon, 30 May 2022 22:31:08 +0200 Subject: [PATCH 3/3] comment out some spamming debug logging --- custom_components/nordpool/__init__.py | 7 +----- custom_components/nordpool/aio_price.py | 8 +++--- custom_components/nordpool/sensor.py | 33 ++++++------------------- 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/custom_components/nordpool/__init__.py b/custom_components/nordpool/__init__.py index aa7345a..37a975c 100644 --- a/custom_components/nordpool/__init__.py +++ b/custom_components/nordpool/__init__.py @@ -24,13 +24,8 @@ RANDOM_SECOND = randint(0, 59) EVENT_NEW_DATA = "nordpool_update" _CURRENCY_LIST = ["DKK", "EUR", "NOK", "SEK"] - - -CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA) - - NAME = DOMAIN -VERSION = "0.0.7" +VERSION = "1.0.0" ISSUEURL = "https://github.com/custom-components/nordpool/issues" STARTUP = f""" diff --git a/custom_components/nordpool/aio_price.py b/custom_components/nordpool/aio_price.py index 1cb854e..9c9d555 100644 --- a/custom_components/nordpool/aio_price.py +++ b/custom_components/nordpool/aio_price.py @@ -95,14 +95,14 @@ def join_result_for_correct_time(results, dt): """ # utc = datetime.utcnow() fin = defaultdict(dict) - _LOGGER.debug("join_result_for_correct_time %s", dt) + # _LOGGER.debug("join_result_for_correct_time %s", dt) utc = dt for day_ in results: for key, value in day_.get("areas", {}).items(): zone = tzs.get(key) if zone is None: - _LOGGER.debug("Skipping %s", key) + # _LOGGER.debug("Skipping %s", key) continue else: zone = tz.gettz(zone) @@ -134,7 +134,7 @@ def join_result_for_correct_time(results, dt): if start_of_day <= local and local <= end_of_day: fin["areas"][key]["values"].append(val) - _LOGGER.debug("Combines result: %s", fin) + # _LOGGER.debug("Combines result: %s", fin) return fin @@ -149,7 +149,7 @@ def __init__(self, currency, client, tz=None): async def _io(self, url, **kwargs): resp = await self.client.get(url, params=kwargs) - _LOGGER.debug("requested %s %s", resp.url, kwargs) + # _LOGGER.debug("requested %s %s", resp.url, kwargs) return await resp.json() diff --git a/custom_components/nordpool/sensor.py b/custom_components/nordpool/sensor.py index 9a944cd..5f3d58f 100644 --- a/custom_components/nordpool/sensor.py +++ b/custom_components/nordpool/sensor.py @@ -1,14 +1,13 @@ -from enum import unique import logging import math -from datetime import datetime from operator import itemgetter from statistics import mean -import homeassistant.util.uuid as uuid_util -from homeassistant.helpers.entity import async_generate_entity_id + + import homeassistant.helpers.config_validation as cv import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA + +# from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import CONF_REGION from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import Entity @@ -57,31 +56,13 @@ DEFAULT_CURRENCY = "NOK" DEFAULT_REGION = "Kr.sand" -DEFAULT_NAME = "Elspot" +DEFAULT_NAME = "Nordpool" ENTITY_ID_FORMAT = DOMAIN + ".{}" DEFAULT_TEMPLATE = "{{0.0|float}}" -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_REGION, default=DEFAULT_REGION): vol.In( - list(_REGIONS.keys()) - ), - vol.Optional("friendly_name", default=""): cv.string, - # This is only needed if you want the some area but want the prices in a non local currency - vol.Optional("currency", default=""): cv.string, - vol.Optional("VAT", default=True): cv.boolean, - vol.Optional("precision", default=3): cv.positive_int, - vol.Optional("low_price_cutoff", default=1.0): cv.small_float, - vol.Optional("price_type", default="kWh"): vol.In(list(_PRICE_IN.keys())), - vol.Optional("price_in_cents", default=False): cv.boolean, - vol.Optional("additional_costs", default=DEFAULT_TEMPLATE): cv.template, - } -) - - def _dry_setup(hass, config, add_devices, discovery_info=None, unique_id=None): """Setup the platform""" _LOGGER.debug("Dumping config %r", config) @@ -250,7 +231,7 @@ def _calc_price(self, value=None, fake_dt=None) -> float: value = self._current_price if value is None or math.isinf(value): - _LOGGER.debug("api returned junk infinty %s", value) + _LOGGER.debug("%s api returned junk infinty %s", self.unique_id, value) return None # Used to inject the current hour. @@ -319,7 +300,7 @@ def _update(self, data) -> None: @property def current_price(self) -> float: res = self._calc_price() - _LOGGER.debug("Current hours price for %s is %s", self.name, res) + _LOGGER.debug("Current hours price for %s is %s", self.unique_id, res) return res def _someday(self, data) -> list: