From c41b0d91a4f5e6750bb057bd08646a70315d8b84 Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Mon, 18 Sep 2023 20:12:15 +0100 Subject: [PATCH 1/5] feat(sensor): Added service for refreshing previous electricity previous consumption data --- .../octopus_energy/binary_sensor.py | 1 - custom_components/octopus_energy/const.py | 1 + .../previous_accumulative_consumption.py | 31 ++++++-- .../electricity/previous_accumulative_cost.py | 4 +- custom_components/octopus_energy/sensor.py | 19 ++++- .../octopus_energy/services.yaml | 16 ++++- .../octopus_energy/statistics/consumption.py | 6 ++ .../octopus_energy/statistics/cost.py | 6 ++ .../octopus_energy/statistics/refresh.py | 72 +++++++++++++++++++ 9 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 custom_components/octopus_energy/statistics/refresh.py diff --git a/custom_components/octopus_energy/binary_sensor.py b/custom_components/octopus_energy/binary_sensor.py index 4c087897..dfa96fad 100644 --- a/custom_components/octopus_energy/binary_sensor.py +++ b/custom_components/octopus_energy/binary_sensor.py @@ -1,4 +1,3 @@ -from datetime import timedelta import logging import voluptuous as vol diff --git a/custom_components/octopus_energy/const.py b/custom_components/octopus_energy/const.py index 8901934d..928266c7 100644 --- a/custom_components/octopus_energy/const.py +++ b/custom_components/octopus_energy/const.py @@ -59,6 +59,7 @@ # However it looks like there are some tariffs that don't fit this mold REGEX_TARIFF_PARTS = "^((?P[A-Z])-(?P[0-9A-Z]+)-)?(?P[A-Z0-9-]+)-(?P[A-Z])$" REGEX_OFFSET_PARTS = "^(-)?([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$" +REGEX_DATE = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" DATA_SCHEMA_ACCOUNT = vol.Schema({ vol.Required(CONFIG_MAIN_API_KEY): str, diff --git a/custom_components/octopus_energy/electricity/previous_accumulative_consumption.py b/custom_components/octopus_energy/electricity/previous_accumulative_consumption.py index 1d5234bf..2dc0fbb0 100644 --- a/custom_components/octopus_energy/electricity/previous_accumulative_consumption.py +++ b/custom_components/octopus_energy/electricity/previous_accumulative_consumption.py @@ -1,9 +1,6 @@ import logging from datetime import datetime -from ..statistics.consumption import async_import_external_statistics_from_consumption - -from homeassistant.core import HomeAssistant -from homeassistant.util.dt import (utcnow) +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, @@ -24,16 +21,21 @@ from .base import (OctopusEnergyElectricitySensor) +from ..statistics.consumption import async_import_external_statistics_from_consumption, get_electricity_consumption_statistic_unique_id +from ..statistics.refresh import async_refresh_previous_electricity_consumption_data +from ..api_client import OctopusEnergyApiClient + _LOGGER = logging.getLogger(__name__) class OctopusEnergyPreviousAccumulativeElectricityConsumption(CoordinatorEntity, OctopusEnergyElectricitySensor, SensorEntity, RestoreEntity): """Sensor for displaying the previous days accumulative electricity reading.""" - def __init__(self, hass: HomeAssistant, coordinator, tariff_code, meter, point): + def __init__(self, hass: HomeAssistant, client: OctopusEnergyApiClient, coordinator, tariff_code, meter, point): """Init sensor.""" super().__init__(coordinator) OctopusEnergyElectricitySensor.__init__(self, hass, meter, point) + self._client = client self._state = None self._tariff_code = tariff_code self._last_reset = None @@ -121,7 +123,7 @@ async def async_update(self): await async_import_external_statistics_from_consumption( self._hass, - f"electricity_{self._serial_number}_{self._mpan}{self._export_id_addition}_previous_accumulative_consumption", + get_electricity_consumption_statistic_unique_id(self._serial_number, self._mpan, self._is_export), self.name, consumption_and_cost["charges"], rate_data, @@ -161,4 +163,19 @@ async def async_added_to_hass(self): if x == "last_reset": self._last_reset = datetime.strptime(state.attributes[x], "%Y-%m-%dT%H:%M:%S%z") - _LOGGER.debug(f'Restored OctopusEnergyPreviousAccumulativeElectricityConsumption state: {self._state}') \ No newline at end of file + _LOGGER.debug(f'Restored OctopusEnergyPreviousAccumulativeElectricityConsumption state: {self._state}') + + @callback + async def async_refresh_previous_consumption_data(self, start_date): + """Update sensors config""" + + await async_refresh_previous_electricity_consumption_data( + self._hass, + self._client, + start_date, + self._mpan, + self._serial_number, + self._tariff_code, + self._is_smart_meter, + self._is_export + ) \ No newline at end of file diff --git a/custom_components/octopus_energy/electricity/previous_accumulative_cost.py b/custom_components/octopus_energy/electricity/previous_accumulative_cost.py index 23d71461..73580e45 100644 --- a/custom_components/octopus_energy/electricity/previous_accumulative_cost.py +++ b/custom_components/octopus_energy/electricity/previous_accumulative_cost.py @@ -18,7 +18,7 @@ from .base import (OctopusEnergyElectricitySensor) -from ..statistics.cost import async_import_external_statistics_from_cost +from ..statistics.cost import async_import_external_statistics_from_cost, get_electricity_cost_statistic_unique_id _LOGGER = logging.getLogger(__name__) @@ -117,7 +117,7 @@ async def async_update(self): _LOGGER.debug(f"Calculated previous electricity consumption cost for '{self._mpan}/{self._serial_number}'...") await async_import_external_statistics_from_cost( self._hass, - f"electricity_{self._serial_number}_{self._mpan}_previous_accumulative_cost", + get_electricity_cost_statistic_unique_id(self._serial_number, self._mpan, self._is_export), self.name, consumption_and_cost["charges"], rate_data, diff --git a/custom_components/octopus_energy/sensor.py b/custom_components/octopus_energy/sensor.py index 2dee8abd..86135ffc 100644 --- a/custom_components/octopus_energy/sensor.py +++ b/custom_components/octopus_energy/sensor.py @@ -1,6 +1,9 @@ +import voluptuous as vol import logging + from homeassistant.util.dt import (utcnow) from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_validation as cv, entity_platform from .electricity.current_consumption import OctopusEnergyCurrentElectricityConsumption from .electricity.current_accumulative_consumption import OctopusEnergyCurrentAccumulativeElectricityConsumption @@ -67,6 +70,20 @@ async def async_setup_entry(hass, entry, async_add_entities): if CONFIG_MAIN_API_KEY in entry.data: await async_setup_default_sensors(hass, entry, async_add_entities) + platform = entity_platform.async_get_current_platform() + platform.async_register_entity_service( + "refresh_previous_consumption_data", + vol.All( + vol.Schema( + { + vol.Optional("start_time"): str, + }, + extra=vol.ALLOW_EXTRA, + ), + ), + "async_refresh_previous_consumption_data", + ) + async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_entities): config = dict(entry.data) @@ -114,7 +131,7 @@ async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_enti electricity_tariff_code, meter["is_smart_meter"] ) - entities.append(OctopusEnergyPreviousAccumulativeElectricityConsumption(hass, previous_consumption_coordinator, electricity_tariff_code, meter, point)) + entities.append(OctopusEnergyPreviousAccumulativeElectricityConsumption(hass, client, previous_consumption_coordinator, electricity_tariff_code, meter, point)) entities.append(OctopusEnergyPreviousAccumulativeElectricityConsumptionPeak(hass, previous_consumption_coordinator, electricity_tariff_code, meter, point)) entities.append(OctopusEnergyPreviousAccumulativeElectricityConsumptionOffPeak(hass, previous_consumption_coordinator, electricity_tariff_code, meter, point)) entities.append(OctopusEnergyPreviousAccumulativeElectricityCost(hass, previous_consumption_coordinator, electricity_tariff_code, meter, point)) diff --git a/custom_components/octopus_energy/services.yaml b/custom_components/octopus_energy/services.yaml index 1d7e8768..b309888a 100644 --- a/custom_components/octopus_energy/services.yaml +++ b/custom_components/octopus_energy/services.yaml @@ -29,4 +29,18 @@ update_target_config: description: The optional offset to apply to the target rate when it starts selector: - text: \ No newline at end of file + text: +refresh_previous_consumption_data: + name: Refresh previous consumption data + description: Refreshes the previous consumption data for a given entity from a given date. + target: + entity: + integration: octopus_energy + domain: sensor + fields: + start_date: + name: Date + description: The date the data should be loaded from. + required: true + selector: + date: \ No newline at end of file diff --git a/custom_components/octopus_energy/statistics/consumption.py b/custom_components/octopus_energy/statistics/consumption.py index f9089e10..17ec9049 100644 --- a/custom_components/octopus_energy/statistics/consumption.py +++ b/custom_components/octopus_energy/statistics/consumption.py @@ -11,6 +11,12 @@ _LOGGER = logging.getLogger(__name__) +def get_electricity_consumption_statistic_unique_id(serial_number: str, mpan: str, is_export: bool): + return f"electricity_{serial_number}_{mpan}{'_export' if is_export == True else ''}_previous_accumulative_consumption" + +def get_electricity_consumption_statistic_name(serial_number: str, mpan: str, is_export: bool): + return f"Electricity {serial_number} {mpan}{' Export' if is_export == True else ''} Previous Accumulative Consumption" + async def async_import_external_statistics_from_consumption( hass: HomeAssistant, unique_id: str, diff --git a/custom_components/octopus_energy/statistics/cost.py b/custom_components/octopus_energy/statistics/cost.py index 61913162..84a09302 100644 --- a/custom_components/octopus_energy/statistics/cost.py +++ b/custom_components/octopus_energy/statistics/cost.py @@ -11,6 +11,12 @@ _LOGGER = logging.getLogger(__name__) +def get_electricity_cost_statistic_unique_id(serial_number: str, mpan: str, is_export: bool): + return f"electricity_{serial_number}_{mpan}{'_export' if is_export == True else ''}_previous_accumulative_cost" + +def get_electricity_cost_statistic_name(serial_number: str, mpan: str, is_export: bool): + return f"Electricity {serial_number} {mpan}{' Export' if is_export == True else ''} Previous Accumulative Cost" + async def async_import_external_statistics_from_cost( hass: HomeAssistant, unique_id: str, diff --git a/custom_components/octopus_energy/statistics/refresh.py b/custom_components/octopus_energy/statistics/refresh.py new file mode 100644 index 00000000..e9d1daa5 --- /dev/null +++ b/custom_components/octopus_energy/statistics/refresh.py @@ -0,0 +1,72 @@ +from datetime import timedelta +import re +import voluptuous as vol + +from homeassistant.core import HomeAssistant +from homeassistant.const import ( + ENERGY_KILO_WATT_HOUR +) + +from homeassistant.util.dt import (now, parse_datetime) + +from ..api_client import OctopusEnergyApiClient +from ..const import REGEX_DATE +from .consumption import async_import_external_statistics_from_consumption, get_electricity_consumption_statistic_name, get_electricity_consumption_statistic_unique_id +from .cost import async_import_external_statistics_from_cost, get_electricity_cost_statistic_name, get_electricity_cost_statistic_unique_id +from ..electricity import calculate_electricity_consumption_and_cost + +async def async_refresh_previous_electricity_consumption_data( + hass: HomeAssistant, + client: OctopusEnergyApiClient, + start_date: str, + mpan: str, + serial_number: str, + tariff_code: str, + is_smart_meter: bool, + is_export: bool +): + # Inputs from automations can include quotes, so remove these + trimmed_date = start_date.strip('\"') + matches = re.search(REGEX_DATE, trimmed_date) + if matches is None: + raise vol.Invalid(f"Date '{trimmed_date}' must match format of YYYY-MM-DD.") + + period_from = parse_datetime(f'{trimmed_date}T00:00:00Z') + while period_from < now(): + period_to = period_from + timedelta(days=7) + + consumption_data = await client.async_get_electricity_consumption(mpan, serial_number, period_from, period_to) + rates = await client.async_get_electricity_rates(tariff_code, is_smart_meter, period_from, period_to) + + consumption_and_cost = calculate_electricity_consumption_and_cost( + consumption_data, + rates, + 0, + None, + tariff_code, + # During BST, two records are returned before the rest of the data is available + 3 + ) + + if consumption_and_cost is not None: + await async_import_external_statistics_from_consumption( + hass, + get_electricity_consumption_statistic_unique_id(serial_number, mpan, is_export), + get_electricity_consumption_statistic_name(serial_number, mpan, is_export), + consumption_and_cost["charges"], + rates, + ENERGY_KILO_WATT_HOUR, + "consumption" + ) + + await async_import_external_statistics_from_cost( + hass, + get_electricity_cost_statistic_unique_id(serial_number, mpan, is_export), + get_electricity_cost_statistic_name(serial_number, mpan, is_export), + consumption_and_cost["charges"], + rates, + "GBP", + "consumption" + ) + + period_from = period_to \ No newline at end of file From 9618465725c64c587dd5b79f76030f5d7a62d11b Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Wed, 20 Sep 2023 03:59:06 +0100 Subject: [PATCH 2/5] fix: Fixed refreshing period --- custom_components/octopus_energy/statistics/refresh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/octopus_energy/statistics/refresh.py b/custom_components/octopus_energy/statistics/refresh.py index e9d1daa5..eb778d27 100644 --- a/custom_components/octopus_energy/statistics/refresh.py +++ b/custom_components/octopus_energy/statistics/refresh.py @@ -33,7 +33,7 @@ async def async_refresh_previous_electricity_consumption_data( period_from = parse_datetime(f'{trimmed_date}T00:00:00Z') while period_from < now(): - period_to = period_from + timedelta(days=7) + period_to = period_from + timedelta(days=2) consumption_data = await client.async_get_electricity_consumption(mpan, serial_number, period_from, period_to) rates = await client.async_get_electricity_rates(tariff_code, is_smart_meter, period_from, period_to) From a52364a4ccaad835c1bc8b013928bf6f847701c9 Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Sun, 24 Sep 2023 09:44:53 +0100 Subject: [PATCH 3/5] chore: Added refresh service for gas consumption --- .../gas/previous_accumulative_consumption.py | 29 +++++-- .../gas/previous_accumulative_cost.py | 4 +- custom_components/octopus_energy/sensor.py | 2 +- .../octopus_energy/statistics/consumption.py | 6 ++ .../octopus_energy/statistics/cost.py | 6 ++ .../octopus_energy/statistics/refresh.py | 83 ++++++++++++++++++- 6 files changed, 118 insertions(+), 12 deletions(-) diff --git a/custom_components/octopus_energy/gas/previous_accumulative_consumption.py b/custom_components/octopus_energy/gas/previous_accumulative_consumption.py index 91825347..eb6f56c7 100644 --- a/custom_components/octopus_energy/gas/previous_accumulative_consumption.py +++ b/custom_components/octopus_energy/gas/previous_accumulative_consumption.py @@ -1,8 +1,7 @@ import logging from datetime import datetime -from ..statistics.consumption import async_import_external_statistics_from_consumption -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, ) @@ -21,17 +20,22 @@ from .base import (OctopusEnergyGasSensor) +from ..api_client import OctopusEnergyApiClient +from ..statistics.consumption import async_import_external_statistics_from_consumption, get_gas_consumption_statistic_unique_id +from ..statistics.refresh import async_refresh_previous_gas_consumption_data + _LOGGER = logging.getLogger(__name__) class OctopusEnergyPreviousAccumulativeGasConsumption(CoordinatorEntity, OctopusEnergyGasSensor, RestoreSensor): """Sensor for displaying the previous days accumulative gas reading.""" - def __init__(self, hass: HomeAssistant, coordinator, tariff_code, meter, point, calorific_value): + def __init__(self, hass: HomeAssistant, client: OctopusEnergyApiClient, coordinator, tariff_code, meter, point, calorific_value): """Init sensor.""" CoordinatorEntity.__init__(self, coordinator) OctopusEnergyGasSensor.__init__(self, hass, meter, point) self._hass = hass + self._client = client self._tariff_code = tariff_code self._native_consumption_units = meter["consumption_units"] self._state = None @@ -122,7 +126,7 @@ async def async_update(self): await async_import_external_statistics_from_consumption( self._hass, - f"gas_{self._serial_number}_{self._mprn}_previous_accumulative_consumption", + get_gas_consumption_statistic_unique_id(self._serial_number, self._mprn), self.name, consumption_and_cost["charges"], rate_data, @@ -165,4 +169,19 @@ async def async_added_to_hass(self): if x == "last_reset": self._last_reset = datetime.strptime(state.attributes[x], "%Y-%m-%dT%H:%M:%S%z") - _LOGGER.debug(f'Restored OctopusEnergyPreviousAccumulativeGasConsumption state: {self._state}') \ No newline at end of file + _LOGGER.debug(f'Restored OctopusEnergyPreviousAccumulativeGasConsumption state: {self._state}') + + @callback + async def async_refresh_previous_consumption_data(self, start_date): + """Update sensors config""" + + await async_refresh_previous_gas_consumption_data( + self._hass, + self._client, + start_date, + self._mprn, + self._serial_number, + self._tariff_code, + self._native_consumption_units, + self._calorific_value, + ) \ No newline at end of file diff --git a/custom_components/octopus_energy/gas/previous_accumulative_cost.py b/custom_components/octopus_energy/gas/previous_accumulative_cost.py index d076c70c..95d0c071 100644 --- a/custom_components/octopus_energy/gas/previous_accumulative_cost.py +++ b/custom_components/octopus_energy/gas/previous_accumulative_cost.py @@ -17,7 +17,7 @@ from .base import (OctopusEnergyGasSensor) -from ..statistics.cost import async_import_external_statistics_from_cost +from ..statistics.cost import async_import_external_statistics_from_cost, get_gas_cost_statistic_unique_id _LOGGER = logging.getLogger(__name__) @@ -121,7 +121,7 @@ async def async_update(self): await async_import_external_statistics_from_cost( self._hass, - f"gas_{self._serial_number}_{self._mprn}_previous_accumulative_cost", + get_gas_cost_statistic_unique_id(self._serial_number, self._mprn), self.name, consumption_and_cost["charges"], rate_data, diff --git a/custom_components/octopus_energy/sensor.py b/custom_components/octopus_energy/sensor.py index 8d16407d..9133f715 100644 --- a/custom_components/octopus_energy/sensor.py +++ b/custom_components/octopus_energy/sensor.py @@ -209,7 +209,7 @@ async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_enti None, previous_gas_consumption_days_offset ) - entities.append(OctopusEnergyPreviousAccumulativeGasConsumption(hass, previous_consumption_coordinator, gas_tariff_code, meter, point, calorific_value)) + entities.append(OctopusEnergyPreviousAccumulativeGasConsumption(hass, client, previous_consumption_coordinator, gas_tariff_code, meter, point, calorific_value)) entities.append(OctopusEnergyPreviousAccumulativeGasConsumptionKwh(hass, previous_consumption_coordinator, gas_tariff_code, meter, point, calorific_value)) entities.append(OctopusEnergyPreviousAccumulativeGasCost(hass, previous_consumption_coordinator, gas_tariff_code, meter, point, calorific_value)) entities.append(OctopusEnergyPreviousAccumulativeGasCostOverride(hass, previous_consumption_coordinator, client, gas_tariff_code, meter, point, calorific_value)) diff --git a/custom_components/octopus_energy/statistics/consumption.py b/custom_components/octopus_energy/statistics/consumption.py index 17ec9049..e2689aaa 100644 --- a/custom_components/octopus_energy/statistics/consumption.py +++ b/custom_components/octopus_energy/statistics/consumption.py @@ -17,6 +17,12 @@ def get_electricity_consumption_statistic_unique_id(serial_number: str, mpan: st def get_electricity_consumption_statistic_name(serial_number: str, mpan: str, is_export: bool): return f"Electricity {serial_number} {mpan}{' Export' if is_export == True else ''} Previous Accumulative Consumption" +def get_gas_consumption_statistic_unique_id(serial_number: str, mpan: str): + return f"gas_{serial_number}_{mpan}_previous_accumulative_consumption" + +def get_gas_consumption_statistic_name(serial_number: str, mpan: str): + return f"Gas {serial_number} {mpan} Previous Accumulative Consumption" + async def async_import_external_statistics_from_consumption( hass: HomeAssistant, unique_id: str, diff --git a/custom_components/octopus_energy/statistics/cost.py b/custom_components/octopus_energy/statistics/cost.py index 84a09302..6cf1e27c 100644 --- a/custom_components/octopus_energy/statistics/cost.py +++ b/custom_components/octopus_energy/statistics/cost.py @@ -17,6 +17,12 @@ def get_electricity_cost_statistic_unique_id(serial_number: str, mpan: str, is_e def get_electricity_cost_statistic_name(serial_number: str, mpan: str, is_export: bool): return f"Electricity {serial_number} {mpan}{' Export' if is_export == True else ''} Previous Accumulative Cost" +def get_gas_cost_statistic_unique_id(serial_number: str, mpan: str): + return f"gas_{serial_number}_{mpan}_previous_accumulative_cost" + +def get_gas_cost_statistic_name(serial_number: str, mpan: str): + return f"Gas {serial_number} {mpan} Previous Accumulative Cost" + async def async_import_external_statistics_from_cost( hass: HomeAssistant, unique_id: str, diff --git a/custom_components/octopus_energy/statistics/refresh.py b/custom_components/octopus_energy/statistics/refresh.py index eb778d27..f9d3d6a4 100644 --- a/custom_components/octopus_energy/statistics/refresh.py +++ b/custom_components/octopus_energy/statistics/refresh.py @@ -3,17 +3,20 @@ import voluptuous as vol from homeassistant.core import HomeAssistant +from homeassistant.components import persistent_notification from homeassistant.const import ( - ENERGY_KILO_WATT_HOUR + ENERGY_KILO_WATT_HOUR, + VOLUME_CUBIC_METERS ) from homeassistant.util.dt import (now, parse_datetime) from ..api_client import OctopusEnergyApiClient from ..const import REGEX_DATE -from .consumption import async_import_external_statistics_from_consumption, get_electricity_consumption_statistic_name, get_electricity_consumption_statistic_unique_id -from .cost import async_import_external_statistics_from_cost, get_electricity_cost_statistic_name, get_electricity_cost_statistic_unique_id +from .consumption import async_import_external_statistics_from_consumption, get_electricity_consumption_statistic_name, get_electricity_consumption_statistic_unique_id, get_gas_consumption_statistic_name, get_gas_consumption_statistic_unique_id +from .cost import async_import_external_statistics_from_cost, get_electricity_cost_statistic_name, get_electricity_cost_statistic_unique_id, get_gas_cost_statistic_name, get_gas_cost_statistic_unique_id from ..electricity import calculate_electricity_consumption_and_cost +from ..gas import calculate_gas_consumption_and_cost async def async_refresh_previous_electricity_consumption_data( hass: HomeAssistant, @@ -69,4 +72,76 @@ async def async_refresh_previous_electricity_consumption_data( "consumption" ) - period_from = period_to \ No newline at end of file + period_from = period_to + + persistent_notification.async_create( + hass, + title="Consumption data imported", + message=f"Consumption data from {start_date} for electricity meter {serial_number}/{mpan} has finished" + ) + +async def async_refresh_previous_gas_consumption_data( + hass: HomeAssistant, + client: OctopusEnergyApiClient, + start_date: str, + mprn: str, + serial_number: str, + tariff_code: str, + consumption_units: str, + calorific_value: float +): + # Inputs from automations can include quotes, so remove these + trimmed_date = start_date.strip('\"') + matches = re.search(REGEX_DATE, trimmed_date) + if matches is None: + raise vol.Invalid(f"Date '{trimmed_date}' must match format of YYYY-MM-DD.") + + period_from = parse_datetime(f'{trimmed_date}T00:00:00Z') + while period_from < now(): + period_to = period_from + timedelta(days=2) + + consumption_data = await client.async_get_gas_consumption(mprn, serial_number, period_from, period_to) + rates = await client.async_get_gas_rates(tariff_code, period_from, period_to) + + consumption_and_cost = calculate_gas_consumption_and_cost( + consumption_data, + rates, + 0, + None, + tariff_code, + consumption_units, + calorific_value, + # During BST, two records are returned before the rest of the data is available + 3 + ) + + if consumption_and_cost is not None: + await async_import_external_statistics_from_consumption( + hass, + get_gas_consumption_statistic_unique_id(serial_number, mprn), + get_gas_consumption_statistic_name(serial_number, mprn), + consumption_and_cost["charges"], + rates, + VOLUME_CUBIC_METERS, + "consumption_m3", + False + ) + + await async_import_external_statistics_from_cost( + hass, + get_gas_cost_statistic_unique_id(serial_number, mprn), + get_gas_cost_statistic_name(serial_number, mprn), + consumption_and_cost["charges"], + rates, + "GBP", + "consumption_kwh", + False + ) + + period_from = period_to + + persistent_notification.async_create( + hass, + title="Consumption data imported", + message=f"Consumption data from {start_date} for gas meter {serial_number}/{mprn} has finished" + ) \ No newline at end of file From 5eec343f549a934d91ce2ff3a9be430165b4e37b Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Sun, 24 Sep 2023 09:53:23 +0100 Subject: [PATCH 4/5] chore: Added additional notifications --- .../octopus_energy/statistics/refresh.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/custom_components/octopus_energy/statistics/refresh.py b/custom_components/octopus_energy/statistics/refresh.py index f9d3d6a4..9283cad8 100644 --- a/custom_components/octopus_energy/statistics/refresh.py +++ b/custom_components/octopus_energy/statistics/refresh.py @@ -34,6 +34,12 @@ async def async_refresh_previous_electricity_consumption_data( if matches is None: raise vol.Invalid(f"Date '{trimmed_date}' must match format of YYYY-MM-DD.") + persistent_notification.async_create( + hass, + title="Consumption data refreshing started", + message=f"Consumption data from {start_date} for electricity meter {serial_number}/{mpan} has started" + ) + period_from = parse_datetime(f'{trimmed_date}T00:00:00Z') while period_from < now(): period_to = period_from + timedelta(days=2) @@ -76,7 +82,7 @@ async def async_refresh_previous_electricity_consumption_data( persistent_notification.async_create( hass, - title="Consumption data imported", + title="Consumption data refreshed", message=f"Consumption data from {start_date} for electricity meter {serial_number}/{mpan} has finished" ) @@ -96,6 +102,12 @@ async def async_refresh_previous_gas_consumption_data( if matches is None: raise vol.Invalid(f"Date '{trimmed_date}' must match format of YYYY-MM-DD.") + persistent_notification.async_create( + hass, + title="Consumption data refreshing started", + message=f"Consumption data from {start_date} for gas meter {serial_number}/{mprn} has started" + ) + period_from = parse_datetime(f'{trimmed_date}T00:00:00Z') while period_from < now(): period_to = period_from + timedelta(days=2) @@ -142,6 +154,6 @@ async def async_refresh_previous_gas_consumption_data( persistent_notification.async_create( hass, - title="Consumption data imported", + title="Consumption data refreshed", message=f"Consumption data from {start_date} for gas meter {serial_number}/{mprn} has finished" ) \ No newline at end of file From 599f11866ca66f1f660159abbffb4b66a577eeca Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Sun, 24 Sep 2023 10:03:01 +0100 Subject: [PATCH 5/5] docs: Added docs around new refresh_previous_consumption_data service --- _docs/setup_account.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/_docs/setup_account.md b/_docs/setup_account.md index 8510e5f1..bd299d8a 100644 --- a/_docs/setup_account.md +++ b/_docs/setup_account.md @@ -12,6 +12,7 @@ - [Government Pricing Caps](#government-pricing-caps) - [Services](#services) - [Service octopus\_energy.purge\_invalid\_external\_statistic\_ids](#service-octopus_energypurge_invalid_external_statistic_ids) + - [Service octopus\_energy.refresh\_previous\_consumption\_data](#service-octopus_energyrefresh_previous_consumption_data) Setup is done entirely via the [integration UI](https://my.home-assistant.io/redirect/config_flow_start/?domain=octopus_energy). @@ -70,4 +71,13 @@ There has been inconsistencies across tariffs on whether government pricing caps ### Service octopus_energy.purge_invalid_external_statistic_ids -Service for removing all external statistics that are associated with meters that don't have an active tariff. This is useful if you've been using the integration and obtained new smart meters. \ No newline at end of file +Service for removing all external statistics that are associated with meters that don't have an active tariff. This is useful if you've been using the integration and obtained new smart meters. + +### Service octopus_energy.refresh_previous_consumption_data + +Service for refreshing the consumption/cost information for a given previous consumption entity. This is useful when you've just installed the integration and want old data brought in or a previous consumption sensor fails to import (e.g. data becomes available outside of the configured offset). The service will raise a notification when the refreshing starts and finishes. + +This service is only available for the following sensors + +- `sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_previous_accumulative_consumption` +- `sensor.octopus_energy_gas_{{METER_SERIAL_NUMBER}}_{{MPRN_NUMBER}}_previous_accumulative_consumption` \ No newline at end of file