diff --git a/custom_components/octopus_energy/__init__.py b/custom_components/octopus_energy/__init__.py index 92f2355c..e57b8bb0 100644 --- a/custom_components/octopus_energy/__init__.py +++ b/custom_components/octopus_energy/__init__.py @@ -14,10 +14,13 @@ from .const import ( DOMAIN, + CONFIG_KIND, CONFIG_MAIN_API_KEY, CONFIG_MAIN_ACCOUNT_ID, CONFIG_MAIN_ELECTRICITY_PRICE_CAP, CONFIG_MAIN_GAS_PRICE_CAP, + CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, + CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, CONFIG_TARGET_NAME, @@ -33,6 +36,31 @@ SCAN_INTERVAL = timedelta(minutes=1) +async def async_migrate_entry(hass, config_entry): + """Migrate old entry.""" + _LOGGER.debug("Migrating from version %s", config_entry.version) + + if config_entry.version == 1: + + new = {**config_entry.data} + + if CONFIG_MAIN_ACCOUNT_ID in config_entry.data: + new[CONFIG_KIND] = "account" + + if "live_consumption_refresh_in_minutes" in new: + + new[CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES] = new["live_consumption_refresh_in_minutes"] + new[CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES] = new["live_consumption_refresh_in_minutes"] + else: + new[CONFIG_KIND] = "target_rate" + + config_entry.version = 2 + hass.config_entries.async_update_entry(config_entry, data=new) + + _LOGGER.debug("Migration to version %s successful", config_entry.version) + + return True + async def async_setup_entry(hass, entry): """This is called from the config flow.""" hass.data.setdefault(DOMAIN, {}) diff --git a/custom_components/octopus_energy/config/main.py b/custom_components/octopus_energy/config/main.py new file mode 100644 index 00000000..b94ebe0f --- /dev/null +++ b/custom_components/octopus_energy/config/main.py @@ -0,0 +1,22 @@ +from ..const import CONFIG_MAIN_ACCOUNT_ID, CONFIG_MAIN_API_KEY, CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION +from ..api_client import OctopusEnergyApiClient + + +async def async_validate_main_config(data): + errors = {} + + client = OctopusEnergyApiClient(data[CONFIG_MAIN_API_KEY]) + account_info = await client.async_get_account(data[CONFIG_MAIN_ACCOUNT_ID]) + + if (account_info is None): + errors[CONFIG_MAIN_API_KEY] = "account_not_found" + + if data[CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION] == True: + + if data[CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES] < 1: + errors[CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES] = "value_greater_than_zero" + + if data[CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES] < 1: + errors[CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES] = "value_greater_than_zero" + + return errors \ No newline at end of file diff --git a/custom_components/octopus_energy/target_rates/config.py b/custom_components/octopus_energy/config/target_rates.py similarity index 99% rename from custom_components/octopus_energy/target_rates/config.py rename to custom_components/octopus_energy/config/target_rates.py index a91d4a83..d70f3c75 100644 --- a/custom_components/octopus_energy/target_rates/config.py +++ b/custom_components/octopus_energy/config/target_rates.py @@ -41,7 +41,6 @@ def is_time_frame_long_enough(hours, start_time, end_time): return available_minutes >= target_minutes - agile_start = parse_datetime(f"2023-08-01T16:00:00Z") agile_end = parse_datetime(f"2023-08-01T23:00:00Z") diff --git a/custom_components/octopus_energy/config_flow.py b/custom_components/octopus_energy/config_flow.py index 2bb1c5cb..da607253 100644 --- a/custom_components/octopus_energy/config_flow.py +++ b/custom_components/octopus_energy/config_flow.py @@ -1,4 +1,3 @@ - import voluptuous as vol import logging @@ -7,14 +6,15 @@ from homeassistant.core import callback import homeassistant.helpers.config_validation as cv -from .target_rates.config import validate_target_rate_config +from .config.target_rates import validate_target_rate_config +from .config.main import async_validate_main_config from .const import ( + CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, + CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, DOMAIN, CONFIG_MAIN_API_KEY, - CONFIG_MAIN_ACCOUNT_ID, CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION, - CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES, CONFIG_MAIN_CALORIFIC_VALUE, CONFIG_MAIN_ELECTRICITY_PRICE_CAP, CONFIG_MAIN_CLEAR_ELECTRICITY_PRICE_CAP, @@ -37,8 +37,6 @@ DATA_ACCOUNT_ID, ) -from .api_client import OctopusEnergyApiClient - from .utils import get_active_tariff_code _LOGGER = logging.getLogger(__name__) @@ -63,32 +61,21 @@ def get_target_rate_meters(account_info, now): class OctopusEnergyConfigFlow(ConfigFlow, domain=DOMAIN): """Config flow.""" - VERSION = 1 + VERSION = 2 async def async_setup_initial_account(self, user_input): """Setup the initial account based on the provided user input""" - errors = {} - - electricity_price_cap = None - if CONFIG_MAIN_ELECTRICITY_PRICE_CAP in user_input: - electricity_price_cap = user_input[CONFIG_MAIN_ELECTRICITY_PRICE_CAP] - - gas_price_cap = None - if CONFIG_MAIN_GAS_PRICE_CAP in user_input: - gas_price_cap = user_input[CONFIG_MAIN_GAS_PRICE_CAP] + errors = await async_validate_main_config(user_input) - client = OctopusEnergyApiClient(user_input[CONFIG_MAIN_API_KEY], electricity_price_cap, gas_price_cap) - account_info = await client.async_get_account(user_input[CONFIG_MAIN_ACCOUNT_ID]) - if (account_info is None): - errors[CONFIG_MAIN_ACCOUNT_ID] = "account_not_found" - return self.async_show_form( - step_id="user", data_schema=DATA_SCHEMA_ACCOUNT, errors=errors + if len(errors) < 1: + # Setup our basic sensors + return self.async_create_entry( + title="Account", + data=user_input ) - # Setup our basic sensors - return self.async_create_entry( - title="Account", - data=user_input + return self.async_show_form( + step_id="user", data_schema=DATA_SCHEMA_ACCOUNT, errors=errors ) async def async_setup_target_rate_schema(self): @@ -234,6 +221,46 @@ async def __async_setup_target_rate_schema(self, config, errors): }), errors=errors ) + + async def __async_setup_main_schema(self, config, errors): + supports_live_consumption = False + if CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION in config: + supports_live_consumption = config[CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION] + + live_electricity_consumption_refresh_in_minutes = 1 + if CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES in config: + live_electricity_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES] + + live_gas_consumption_refresh_in_minutes = 2 + if CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES in config: + live_gas_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES] + + calorific_value = 40 + if CONFIG_MAIN_CALORIFIC_VALUE in config: + calorific_value = config[CONFIG_MAIN_CALORIFIC_VALUE] + + electricity_price_cap_key = vol.Optional(CONFIG_MAIN_ELECTRICITY_PRICE_CAP) + if (CONFIG_MAIN_ELECTRICITY_PRICE_CAP in config): + electricity_price_cap_key = vol.Optional(CONFIG_MAIN_ELECTRICITY_PRICE_CAP, default=config[CONFIG_MAIN_ELECTRICITY_PRICE_CAP]) + + gas_price_cap_key = vol.Optional(CONFIG_MAIN_GAS_PRICE_CAP) + if (CONFIG_MAIN_GAS_PRICE_CAP in config): + gas_price_cap_key = vol.Optional(CONFIG_MAIN_GAS_PRICE_CAP, default=config[CONFIG_MAIN_GAS_PRICE_CAP]) + + return self.async_show_form( + step_id="user", data_schema=vol.Schema({ + vol.Required(CONFIG_MAIN_API_KEY, default=config[CONFIG_MAIN_API_KEY]): str, + vol.Required(CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION, default=supports_live_consumption): bool, + vol.Required(CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, default=live_electricity_consumption_refresh_in_minutes): cv.positive_int, + vol.Required(CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, default=live_gas_consumption_refresh_in_minutes): cv.positive_int, + vol.Required(CONFIG_MAIN_CALORIFIC_VALUE, default=calorific_value): cv.positive_float, + electricity_price_cap_key: cv.positive_float, + vol.Required(CONFIG_MAIN_CLEAR_ELECTRICITY_PRICE_CAP): bool, + gas_price_cap_key: cv.positive_float, + vol.Required(CONFIG_MAIN_CLEAR_GAS_PRICE_CAP): bool, + }), + errors=errors + ) async def async_step_init(self, user_input): """Manage the options for the custom component.""" @@ -243,38 +270,7 @@ async def async_step_init(self, user_input): if self._entry.options is not None: config.update(self._entry.options) - supports_live_consumption = False - if CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION in config: - supports_live_consumption = config[CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION] - - live_consumption_refresh_in_minutes = 1 - if CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES in config: - live_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES] - - calorific_value = 40 - if CONFIG_MAIN_CALORIFIC_VALUE in config: - calorific_value = config[CONFIG_MAIN_CALORIFIC_VALUE] - - electricity_price_cap_key = vol.Optional(CONFIG_MAIN_ELECTRICITY_PRICE_CAP) - if (CONFIG_MAIN_ELECTRICITY_PRICE_CAP in config): - electricity_price_cap_key = vol.Optional(CONFIG_MAIN_ELECTRICITY_PRICE_CAP, default=config[CONFIG_MAIN_ELECTRICITY_PRICE_CAP]) - - gas_price_cap_key = vol.Optional(CONFIG_MAIN_GAS_PRICE_CAP) - if (CONFIG_MAIN_GAS_PRICE_CAP in config): - gas_price_cap_key = vol.Optional(CONFIG_MAIN_GAS_PRICE_CAP, default=config[CONFIG_MAIN_GAS_PRICE_CAP]) - - return self.async_show_form( - step_id="user", data_schema=vol.Schema({ - vol.Required(CONFIG_MAIN_API_KEY, default=config[CONFIG_MAIN_API_KEY]): str, - vol.Required(CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION, default=supports_live_consumption): bool, - vol.Required(CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES, default=live_consumption_refresh_in_minutes): cv.positive_int, - vol.Required(CONFIG_MAIN_CALORIFIC_VALUE, default=calorific_value): cv.positive_float, - electricity_price_cap_key: cv.positive_float, - vol.Required(CONFIG_MAIN_CLEAR_ELECTRICITY_PRICE_CAP): bool, - gas_price_cap_key: cv.positive_float, - vol.Required(CONFIG_MAIN_CLEAR_GAS_PRICE_CAP): bool, - }) - ) + return await self.__async_setup_main_schema(config, {}) elif CONFIG_TARGET_TYPE in self._entry.data: config = dict(self._entry.data) if self._entry.options is not None: @@ -297,6 +293,11 @@ async def async_step_user(self, user_input): if config[CONFIG_MAIN_CLEAR_GAS_PRICE_CAP] == True: del config[CONFIG_MAIN_GAS_PRICE_CAP] + errors = await async_validate_main_config(config) + + if (len(errors) > 0): + return await self.__async_setup_target_rate_schema(config, errors) + return self.async_create_entry(title="", data=config) return self.async_abort(reason="not_supported") @@ -315,7 +316,7 @@ async def async_step_target_rate(self, user_input): errors = validate_target_rate_config(user_input, account_info, now) if (len(errors) > 0): - return await self.__async_setup_target_rate_schema(config, errors) + return await self.__async_setup_main_schema(config, errors) return self.async_create_entry(title="", data=config) diff --git a/custom_components/octopus_energy/const.py b/custom_components/octopus_energy/const.py index 8901934d..37b5eca9 100644 --- a/custom_components/octopus_energy/const.py +++ b/custom_components/octopus_energy/const.py @@ -3,16 +3,21 @@ DOMAIN = "octopus_energy" +CONFIG_KIND = "kind" CONFIG_MAIN_API_KEY = "Api key" CONFIG_MAIN_ACCOUNT_ID = "Account Id" CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION = "supports_live_consumption" -CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES = "live_consumption_refresh_in_minutes" +CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES = "live_electricity_consumption_refresh_in_minutes" +CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES = "live_gas_consumption_refresh_in_minutes" CONFIG_MAIN_CALORIFIC_VALUE = "calorific_value" CONFIG_MAIN_ELECTRICITY_PRICE_CAP = "electricity_price_cap" CONFIG_MAIN_CLEAR_ELECTRICITY_PRICE_CAP = "clear_electricity_price_cap" CONFIG_MAIN_GAS_PRICE_CAP = "gas_price_cap" CONFIG_MAIN_CLEAR_GAS_PRICE_CAP = "clear_gas_price_cap" +CONFIG_DEFAULT_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES = 1 +CONFIG_DEFAULT_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES = 2 + CONFIG_TARGET_NAME = "Name" CONFIG_TARGET_HOURS = "Hours" CONFIG_TARGET_TYPE = "Type" @@ -64,7 +69,8 @@ vol.Required(CONFIG_MAIN_API_KEY): str, vol.Required(CONFIG_MAIN_ACCOUNT_ID): str, vol.Required(CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION): bool, - vol.Required(CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES, default=1): cv.positive_int, + vol.Required(CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, default=CONFIG_DEFAULT_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES): cv.positive_int, + vol.Required(CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, default=CONFIG_DEFAULT_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES): cv.positive_int, vol.Required(CONFIG_MAIN_CALORIFIC_VALUE, default=40.0): cv.positive_float, vol.Optional(CONFIG_MAIN_ELECTRICITY_PRICE_CAP): cv.positive_float, vol.Optional(CONFIG_MAIN_GAS_PRICE_CAP): cv.positive_float diff --git a/custom_components/octopus_energy/sensor.py b/custom_components/octopus_energy/sensor.py index 2dee8abd..0953a92c 100644 --- a/custom_components/octopus_energy/sensor.py +++ b/custom_components/octopus_energy/sensor.py @@ -43,11 +43,14 @@ from .utils import (get_active_tariff_code) from .const import ( + CONFIG_DEFAULT_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, + CONFIG_DEFAULT_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, + CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES, + CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES, DOMAIN, CONFIG_MAIN_API_KEY, CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION, - CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES, CONFIG_MAIN_CALORIFIC_VALUE, CONFIG_MAIN_ELECTRICITY_PRICE_CAP, CONFIG_MAIN_GAS_PRICE_CAP, @@ -123,9 +126,9 @@ async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_enti entities.append(OctopusEnergyPreviousAccumulativeElectricityCostOverride(hass, previous_consumption_coordinator, client, electricity_tariff_code, meter, point)) if meter["is_export"] == False and CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION in config and config[CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION] == True: - live_consumption_refresh_in_minutes = 1 - if CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES in config: - live_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES] + live_consumption_refresh_in_minutes = CONFIG_DEFAULT_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES + if CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES in config: + live_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_ELECTRICITY_CONSUMPTION_REFRESH_IN_MINUTES] consumption_coordinator = await async_create_current_consumption_coordinator(hass, client, meter["device_id"], True, live_consumption_refresh_in_minutes) entities.append(OctopusEnergyCurrentElectricityConsumption(hass, consumption_coordinator, meter, point)) @@ -182,9 +185,9 @@ async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_enti entities.append(OctopusEnergyPreviousAccumulativeGasCostOverride(hass, previous_consumption_coordinator, client, gas_tariff_code, meter, point, calorific_value)) if CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION in config and config[CONFIG_MAIN_SUPPORTS_LIVE_CONSUMPTION] == True: - live_consumption_refresh_in_minutes = 1 - if CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES in config: - live_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_CONSUMPTION_REFRESH_IN_MINUTES] + live_consumption_refresh_in_minutes = CONFIG_DEFAULT_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES + if CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES in config: + live_consumption_refresh_in_minutes = config[CONFIG_MAIN_LIVE_GAS_CONSUMPTION_REFRESH_IN_MINUTES] consumption_coordinator = await async_create_current_consumption_coordinator(hass, client, meter["device_id"], False, live_consumption_refresh_in_minutes) entities.append(OctopusEnergyCurrentGasConsumption(hass, consumption_coordinator, meter, point)) diff --git a/custom_components/octopus_energy/target_rates/repairs.py b/custom_components/octopus_energy/target_rates/repairs.py index 55457981..f50df8f8 100644 --- a/custom_components/octopus_energy/target_rates/repairs.py +++ b/custom_components/octopus_energy/target_rates/repairs.py @@ -3,7 +3,7 @@ from homeassistant.helpers import issue_registry as ir from ..const import CONFIG_TARGET_NAME, DOMAIN -from .config import validate_target_rate_config +from ..config.target_rates import validate_target_rate_config def check_for_errors(hass, config, account_info, now: datetime): if account_info is not None: diff --git a/custom_components/octopus_energy/target_rates/target_rate.py b/custom_components/octopus_energy/target_rates/target_rate.py index 027a1fee..10ef98cb 100644 --- a/custom_components/octopus_energy/target_rates/target_rate.py +++ b/custom_components/octopus_energy/target_rates/target_rate.py @@ -36,7 +36,7 @@ get_target_rate_info ) -from .config import validate_target_rate_config +from ..config.target_rates import validate_target_rate_config from ..target_rates.repairs import check_for_errors _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/octopus_energy/translations/en.json b/custom_components/octopus_energy/translations/en.json index 1f761d26..eddee8ae 100644 --- a/custom_components/octopus_energy/translations/en.json +++ b/custom_components/octopus_energy/translations/en.json @@ -9,6 +9,8 @@ "Account Id": "Your account Id (e.g. A-AAAA1111)", "supports_live_consumption": "I have a Home Mini - https://octopus.energy/blog/octopus-home-mini/", "live_consumption_refresh_in_minutes": "Home Mini refresh rate in minutes", + "live_electricity_consumption_refresh_in_minutes": "Home Mini electricity refresh rate in minutes", + "live_gas_consumption_refresh_in_minutes": "Home Mini gas refresh rate in minutes", "calorific_value": "Gas calorific value. This can be found on your gas statement and can change from time to time.", "electricity_price_cap": "Optional electricity price cap in pence", "gas_price_cap": "Optional gas price cap in pence" @@ -31,7 +33,8 @@ } }, "error": { - "account_not_found": "Account information was not found", + "account_not_found": "Invalid API key or account id specified", + "value_greater_than_zero": "Value must be greater or equal to 1", "invalid_target_hours": "Target hours must be in half hour increments (e.g. 0.5 = 30 minutes; 1 = 60 minutes).", "invalid_target_name": "Name must only include lower case alpha characters and underscore (e.g. my_target)", "invalid_target_time": "Must be in the format HH:MM", @@ -52,7 +55,8 @@ "data": { "Api key": "Api key", "supports_live_consumption": "I have a Home Mini - https://octopus.energy/blog/octopus-home-mini/", - "live_consumption_refresh_in_minutes": "Home Mini refresh rate in minutes", + "live_electricity_consumption_refresh_in_minutes": "Home Mini electricity refresh rate in minutes", + "live_gas_consumption_refresh_in_minutes": "Home Mini gas refresh rate in minutes", "calorific_value": "Gas calorific value. This can be found on your gas statement and can change from time to time.", "electricity_price_cap": "Optional electricity price cap in pence", "clear_electricity_price_cap": "Clear electricity price cap", @@ -76,6 +80,8 @@ } }, "error": { + "account_not_found": "Invalid API key or account id specified", + "value_greater_than_zero": "Value must be greater or equal to 1", "invalid_target_hours": "Target hours must be in half hour increments (e.g. 0.5 = 30 minutes; 1 = 60 minutes).", "invalid_target_time": "Must be in the format HH:MM", "invalid_offset": "Offset must be in the form of HH:MM:SS with an optional negative symbol", diff --git a/tests/unit/target_rates/test_validate_target_rate_config.py b/tests/unit/config/test_validate_target_rate_config.py similarity index 99% rename from tests/unit/target_rates/test_validate_target_rate_config.py rename to tests/unit/config/test_validate_target_rate_config.py index 2e0a699a..8efb568f 100644 --- a/tests/unit/target_rates/test_validate_target_rate_config.py +++ b/tests/unit/config/test_validate_target_rate_config.py @@ -1,7 +1,7 @@ import pytest from homeassistant.util.dt import (as_utc, parse_datetime) -from custom_components.octopus_energy.target_rates.config import validate_target_rate_config +from custom_components.octopus_energy.config.target_rates import validate_target_rate_config from custom_components.octopus_energy.const import CONFIG_TARGET_END_TIME, CONFIG_TARGET_HOURS, CONFIG_TARGET_MPAN, CONFIG_TARGET_NAME, CONFIG_TARGET_OFFSET, CONFIG_TARGET_START_TIME now = as_utc(parse_datetime("2023-08-20T10:00:00Z"))