Skip to content

Commit

Permalink
feat: Added cost tracker for weekly and monthly accumulations
Browse files Browse the repository at this point in the history
  • Loading branch information
BottlecapDave committed Mar 3, 2024
1 parent 0708271 commit 01c3733
Show file tree
Hide file tree
Showing 14 changed files with 681 additions and 21 deletions.
126 changes: 126 additions & 0 deletions _docs/setup/cost_tracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,132 @@ This is the total cost of the tracked entity at off peak rate for the current da
| `is_tracking` | `boolean` | Determines if the tracker is currently tracking consumption/cost data |
| `total_consumption` | `float` | The total consumption that has been tracked for the current day at off peak rate |

### Week cost sensor

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_week`

This is the total cost of the tracked entity for the current week. This will reset on the configured day.

This is in pounds and pence (e.g. 1.01 = £1.01).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `accumulated_data` | `array` | The collection of accumulated cost in daily increments |
| `total_consumption` | `float` | The total consumption that has been tracked for the current week |

Each item within the `accumulated_data` has the following attributes

| Attribute | Type | Description |
|-----------|------|-------------|
| `start` | `datetime` | The date/time when the consumption starts |
| `end` | `datetime` | The date/time when the consumption ends |
| `consumption` | `float` | The consumption value of the specified period |
| `cost` | `float` | The cost of the consumption at the specified rate. This is in pounds and pence (e.g. 1.01 = £1.01) |

### Week cost sensor (Peak)

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_week_peak`

This is the total cost of the tracked entity at peak rate for the current week. This is in pounds and pence (e.g. 1.01 = £1.01).

!!! note
This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `total_consumption` | `float` | The total consumption that has been tracked for the current week at peak rate |

### Week cost sensor (Off Peak)

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_week_off_peak`

This is the total cost of the tracked entity at off peak rate for the current week. This is in pounds and pence (e.g. 1.01 = £1.01).

!!! note
This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `total_consumption` | `float` | The total consumption that has been tracked for the current week at off peak rate |

### Month cost sensor

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_month`

This is the total cost of the tracked entity for the current month. This will reset on the configured day.

This is in pounds and pence (e.g. 1.01 = £1.01).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `accumulated_data` | `array` | The collection of accumulated cost in daily increments |
| `total_consumption` | `float` | The total consumption that has been tracked for the current month |

Each item within the `accumulated_data` has the following attributes

| Attribute | Type | Description |
|-----------|------|-------------|
| `start` | `datetime` | The date/time when the consumption starts |
| `end` | `datetime` | The date/time when the consumption ends |
| `consumption` | `float` | The consumption value of the specified period |
| `cost` | `float` | The cost of the consumption at the specified rate. This is in pounds and pence (e.g. 1.01 = £1.01) |

### Month cost sensor (Peak)

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_month_peak`

This is the total cost of the tracked entity at peak rate for the current month. This is in pounds and pence (e.g. 1.01 = £1.01).

!!! note
This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `total_consumption` | `float` | The total consumption that has been tracked for the current month at peak rate |

### Month cost sensor (Off Peak)

`sensor.octopus_energy_cost_tracker_{{COST_TRACKER_NAME}}_month_off_peak`

This is the total cost of the tracked entity at off peak rate for the current month. This is in pounds and pence (e.g. 1.01 = £1.01).

!!! note
This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them).

| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `string` | The base name of the cost tracker (based on config) |
| `mpan` | `string` | The mpan of the meter that determines how the cost is calculated (based on config) |
| `target_entity_id` | `string` | The entity whose consumption data is being tracked (based on config) |
| `entity_accumulative_value` | `boolean` | Determines if the tracked entity has accumulative data (based on config) |
| `account_id` | `string` | The id of the account the cost tracker is for (based on config) |
| `total_consumption` | `float` | The total consumption that has been tracked for the current month at off peak rate |

## Services

There are services available associated with cost tracker sensors. Please review them in the [services doc](../services.md#octopus_energyupdate_cost_tracker).
6 changes: 4 additions & 2 deletions custom_components/octopus_energy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,12 @@ async def async_unload_entry(hass, entry):
"""Unload a config entry."""

unload_ok = False
if CONFIG_MAIN_API_KEY in entry.data:
if entry.data[CONFIG_KIND] == CONFIG_KIND_ACCOUNT:
unload_ok = await hass.config_entries.async_unload_platforms(entry, ACCOUNT_PLATFORMS)
elif CONFIG_TARGET_NAME in entry.data:
elif entry.data[CONFIG_KIND] == CONFIG_KIND_TARGET_RATE:
unload_ok = await hass.config_entries.async_unload_platforms(entry, TARGET_RATE_PLATFORMS)
elif entry.data[CONFIG_KIND] == CONFIG_KIND_COST_TRACKER:
unload_ok = await hass.config_entries.async_unload_platforms(entry, COST_TRACKER_PLATFORMS)

return unload_ok

Expand Down
2 changes: 2 additions & 0 deletions custom_components/octopus_energy/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
CONFIG_COST_MPAN = "mpan"
CONFIG_COST_TARGET_ENTITY_ID = "target_entity_id"
CONFIG_COST_ENTITY_ACCUMULATIVE_VALUE = "entity_accumulative_value"
CONFIG_COST_WEEKDAY_RESET = "weekday_reset"
CONFIG_COST_MONTH_DAY_RESET = "month_day_reset"

DATA_CONFIG = "CONFIG"
DATA_ELECTRICITY_RATES_COORDINATOR_KEY = "ELECTRICITY_RATES_COORDINATOR_{}_{}"
Expand Down
50 changes: 49 additions & 1 deletion custom_components/octopus_energy/cost_tracker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,52 @@ def add_consumption(current: datetime,
else:
new_untracked_consumption_data = __add_consumption(new_untracked_consumption_data, target_start, target_end, value)

return CostTrackerResult(new_tracked_consumption_data, new_untracked_consumption_data)
return CostTrackerResult(new_tracked_consumption_data, new_untracked_consumption_data)

class AccumulativeCostTrackerResult:
accumulative_data: list
total_consumption: float
total_cost: float

def __init__(self, accumulative_data: list, total_consumption: float, total_cost: float):
self.accumulative_data = accumulative_data
self.total_consumption = total_consumption
self.total_cost = total_cost

def accumulate_cost(current: datetime, accumulative_data: list, new_cost: float, new_consumption: float) -> AccumulativeCostTrackerResult:
start_of_day = current.replace(hour=0, minute=0, second=0, microsecond=0)

if accumulative_data is None:
accumulative_data = []

total_cost = 0
total_consumption = 0
is_day_added = False
new_accumulative_data = []
for item in accumulative_data:
new_item = item.copy()

if "start" in new_item and new_item["start"] == start_of_day:
new_item["cost"] = new_cost
new_item["consumption"] = new_consumption
is_day_added = True

if "consumption" in new_item:
total_consumption += new_item["consumption"]

if "cost" in new_item:
total_cost += new_item["cost"]

new_accumulative_data.append(new_item)

if is_day_added == False:
new_accumulative_data.append({
"start": start_of_day,
"end": start_of_day + timedelta(days=1),
"cost": new_cost,
"consumption": new_consumption,
})

return AccumulativeCostTrackerResult(new_accumulative_data, total_consumption, total_cost)


Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,17 @@
class OctopusEnergyCostTrackerSensor(CoordinatorEntity, RestoreSensor):
"""Sensor for calculating the cost for a given sensor."""

def __init__(self, hass: HomeAssistant, coordinator, config, is_export):
def __init__(self, hass: HomeAssistant, coordinator, config):
"""Init sensor."""
# Pass coordinator to base class
CoordinatorEntity.__init__(self, coordinator)

self._state = None
self._config = config
self._is_export = is_export
self._attributes = self._config.copy()
self._attributes["is_tracking"] = True
self._attributes["tracked_charges"] = []
self._attributes["untracked_charges"] = []
self._is_export = is_export
self._last_reset = None

self._hass = hass
Expand Down
Loading

0 comments on commit 01c3733

Please sign in to comment.