Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/refresh previous consumption service #422

Merged
merged 7 commits into from
Sep 25, 2023
12 changes: 11 additions & 1 deletion _docs/setup_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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.
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`
1 change: 0 additions & 1 deletion custom_components/octopus_energy/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from datetime import timedelta
import logging

import voluptuous as vol
Expand Down
1 change: 1 addition & 0 deletions custom_components/octopus_energy/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
# However it looks like there are some tariffs that don't fit this mold
REGEX_TARIFF_PARTS = "^((?P<energy>[A-Z])-(?P<rate>[0-9A-Z]+)-)?(?P<product_code>[A-Z0-9-]+)-(?P<region>[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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -23,16 +20,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, RestoreSensor):
"""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."""
CoordinatorEntity.__init__(self, coordinator)
OctopusEnergyElectricitySensor.__init__(self, hass, meter, point)

self._client = client
self._state = None
self._tariff_code = tariff_code
self._last_reset = None
Expand Down Expand Up @@ -120,7 +122,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,
Expand Down Expand Up @@ -160,4 +162,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}')
_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
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,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__)

Expand Down Expand Up @@ -116,7 +116,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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
)
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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}')
_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,
)
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down Expand Up @@ -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,
Expand Down
21 changes: 19 additions & 2 deletions custom_components/octopus_energy/sensor.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -73,6 +76,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)

Expand Down Expand Up @@ -125,7 +142,7 @@ async def async_setup_default_sensors(hass: HomeAssistant, entry, async_add_enti
meter["is_smart_meter"],
previous_electricity_consumption_days_offset
)
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))
Expand Down Expand Up @@ -192,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))
Expand Down
17 changes: 15 additions & 2 deletions custom_components/octopus_energy/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@ update_target_config:
The optional offset to apply to the target rate when it starts
selector:
text:

purge_invalid_external_statistic_ids:
name: Purge invalid external statistics
description: Removes external statistics for all meters that don't have an active tariff
description: Removes external statistics for all meters that don't have an active tariff
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:
12 changes: 12 additions & 0 deletions custom_components/octopus_energy/statistics/consumption.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@

_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"

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,
Expand Down
12 changes: 12 additions & 0 deletions custom_components/octopus_energy/statistics/cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@

_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"

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,
Expand Down
Loading
Loading