Skip to content

Commit

Permalink
feat: Updated off peak sensor to include current start/end and next s…
Browse files Browse the repository at this point in the history
…tart/end times as attributes
  • Loading branch information
BottlecapDave committed Jan 30, 2024
1 parent 443a130 commit 8da4679
Show file tree
Hide file tree
Showing 6 changed files with 310 additions and 25 deletions.
58 changes: 53 additions & 5 deletions _docs/entities/electricity.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ This is `on` when you're within your tariff's off peak period, and `off` at all

For intelligent tariffs, this sensor will only turn on during the standard off peak period. If you are wanting to know when extended off peak rates are available, you'll want to use the [is dispatching](./intelligent.md#is-dispatching) sensor.

| Attribute | Type | Description |
|-----------|------|-------------|
| `current_start` | `datetime` | The date/time when the off peak rate started |
| `current_end` | `datetime` | The date/time when the off peak rate ends |
| `next_start` | `datetime` | The date/time when the next off peak rate starts |
| `next_end` | `datetime` | The date/time when the next off peak rate ends |

## Smart Meter Entities

If your account information doesn't determine you have a smart meter, then you will have the following entities in a disabled state. If you enable these entities, they might not work correctly in this scenario.
Expand Down Expand Up @@ -275,16 +282,20 @@ Each rate item has the following attributes

## Export Entities

If you export energy, then in addition you'll gain the above entities with the name `export` present. E.g. `sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_export_current_rate`.
If you export energy, then unless specified otherwise, in addition you'll gain the above entities with the name `export` present. E.g. `sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_export_current_rate`.

## Home Mini Entities

### Current Consumption

> This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one
`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_consumption`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The latest electricity consumption sent to Octopus Energy. This will update every minute. This is a legacy sensor which was been built to see the accumulation within the energy dashboard. This _may_ be removed in the future.

It has been noticed that daily consumption reported in Home Assistant can differ to when looking at past data within Octopus Energy. It looks like this is because Octopus Energy will favour "official" data from your smart meter over the data they collect.
Expand All @@ -297,10 +308,11 @@ If current consumption data is unable to be retrieved, then the integration will

### Current Demand

> This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one
`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_demand`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

The current demand reported by the Home Mini. This will try and update every minute.

| Attribute | Type | Description |
Expand All @@ -311,6 +323,12 @@ The current demand reported by the Home Mini. This will try and update every min

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_consumption`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total consumption reported by the meter for the current day.

| Attribute | Type | Description |
Expand All @@ -334,6 +352,12 @@ Each charge item has the following attributes

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_consumption_peak`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total consumption reported by the meter for the current day that applied during peak hours. This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them). This will only be populated if you're on a tariff with two available rates.

| Attribute | Type | Description |
Expand All @@ -347,6 +371,12 @@ The total consumption reported by the meter for the current day that applied dur

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_consumption_off_peak`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total consumption reported by the meter for the current day that applied during off peak hours. This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them). This will only be populated if you're on a tariff with two available rates.

| Attribute | Type | Description |
Expand All @@ -360,6 +390,12 @@ The total consumption reported by the meter for the current day that applied dur

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_cost`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total cost for the current day, including the standing charge.

| Attribute | Type | Description |
Expand Down Expand Up @@ -388,6 +424,12 @@ Each charge item has the following attributes

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_cost_peak`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total cost for the current day that applied during peak hours. This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them). This will only be populated if you're on a tariff with two available rates.

| Attribute | Type | Description |
Expand All @@ -401,6 +443,12 @@ The total cost for the current day that applied during peak hours. This is [disa

`sensor.octopus_energy_electricity_{{METER_SERIAL_NUMBER}}_{{MPAN_NUMBER}}_current_accumulative_cost_off_peak`

!!! warning
This will only be available if you have specified you have a [Octopus Home Mini](../setup/account.md#home-mini). Do not set unless you have one

!!! info
An export equivalent of this sensor does not exist because the data is not available

The total cost for the current day that applied during off peak hours. This is [disabled by default](../faq.md#there-are-entities-that-are-disabled-why-are-they-disabled-and-how-do-i-enable-them). This will only be populated if you're on a tariff with two available rates.

| Attribute | Type | Description |
Expand Down
14 changes: 14 additions & 0 deletions _docs/entities/intelligent.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,17 @@ This sensor is used to see and set the ready time for your future intelligent ch
|-----------|------|-------------|
| `last_evaluated` | `datetime` | The date/time the value was last evaluated |
| `data_last_retrieved` | `datetime` | The date/time the underlying data was last retrieved from Octopus Energy APIs |

## Migrating from megakid/ha_octopus_intelligent?

If you're moving to this integration from [megakid/ha_octopus_intelligent](https://github.com/megakid/ha_octopus_intelligent), below is a quick guide on what entities you should use

* `binary_sensor.octopus_intelligent_slot` - Use the [is dispatching sensor](#is-dispatching)
* `binary_sensor.octopus_intelligent_planned_dispatch_slot` - There is no alternative for this.
* `binary_sensor.octopus_intelligent_slot_next_1_hour`, `binary_sensor.octopus_intelligent_slot_next_2_hours` and `binary_sensor.octopus_intelligent_slot_next_3_hours` - These sensors felt like they would always fall short of peoples requirements as everyone has different time periods they wish to know about. There is currently no alternative for this, but there are plans to expose current and next start/end times as attributes on the sensor.
* `sensor.octopus_intelligent_next_offpeak_start` - The default off peak start date/time can be found as an attribute on the [off peak sensor](./electricity.md#off-peak). This can be extracted using a [template sensor](https://www.home-assistant.io/integrations/template/).
* `sensor.octopus_intelligent_offpeak_end` - The default off peak end date/time can be found as an attribute on the [off peak sensor](./electricity.md#off-peak). This can be extracted using a [template sensor](https://www.home-assistant.io/integrations/template/).
* `switch.octopus_intelligent_bump_charge` - Use the [bump charge sensor](#bump-charge)
* `switch.octopus_intelligent_smart_charging` - Use the [smart charge sensor](#smart-charge)
* `select.octopus_intelligent_target_time` - Use the [ready time sensor](#ready-time)
* `select.octopus_intelligent_target_soc` - Use the [charge limit sensor](#charge-limit)
33 changes: 30 additions & 3 deletions custom_components/octopus_energy/electricity/off_peak.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)
from homeassistant.helpers.restore_state import RestoreEntity

from ..utils import is_off_peak
from ..utils import get_off_peak_times, is_off_peak

from .base import OctopusEnergyElectricitySensor
from ..utils.attributes import dict_to_typed_dict
Expand All @@ -34,7 +34,12 @@ def __init__(self, hass: HomeAssistant, coordinator, meter, point):
OctopusEnergyElectricitySensor.__init__(self, hass, meter, point)

self._state = None
self._attributes = {}
self._attributes = {
"current_start": None,
"current_end": None,
"next_start": None,
"next_end": None,
}
self._last_updated = None

self.entity_id = generate_entity_id("binary_sensor.{}", self.unique_id, hass=hass)
Expand Down Expand Up @@ -71,7 +76,29 @@ def _handle_coordinator_update(self) -> None:
if (rates is not None and (self._last_updated is None or self._last_updated < (current - timedelta(minutes=30)) or (current.minute % 30) == 0)):
_LOGGER.debug(f"Updating OctopusEnergyElectricityOffPeak for '{self._mpan}/{self._serial_number}'")

self._state = is_off_peak(current, rates)
self._state = False
self._attributes = {
"current_start": None,
"current_end": None,
"next_start": None,
"next_end": None,
}

times = get_off_peak_times(current, rates)
if times is not None and len(times) > 0:
time = times.pop(0)
if time.start <= current:
self._attributes["current_start"] = time.start
self._attributes["current_end"] = time.end
self._state = True

if len(times) > 0:
self._attributes["next_start"] = times[0].start
self._attributes["next_end"] = times[0].end
else:
self._attributes["next_start"] = time.start
self._attributes["next_end"] = time.end


self._last_updated = current

Expand Down
30 changes: 30 additions & 0 deletions custom_components/octopus_energy/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,36 @@ def is_off_peak(current: datetime, rates):
rate_information["current_rate"]["is_intelligent_adjusted"] == False and
value_inc_vat_to_pounds(off_peak_value) == rate_information["current_rate"]["value_inc_vat"])

class OffPeakTimes:
start: datetime
end: datetime

def __init__(self, start, end):
self.start = start
self.end = end

def get_off_peak_times(current: datetime, rates: list):
off_peak_value = get_off_peak_cost(current, rates)
times: list[OffPeakTimes] = []

if rates is not None and off_peak_value is not None:
start = None
rates_length = len(rates)
for rate_index in range(rates_length):
rate = rates[rate_index]
if (rate["value_inc_vat"] == off_peak_value and
("is_intelligent_adjusted" not in rate or rate["is_intelligent_adjusted"] == False)):
if start is None:
start = rate["start"]
elif start is not None:
end = rates[rate_index - 1]["end"]
if end >= current:
print(start, end)
times.append(OffPeakTimes(start, end))
start = None

return times

def private_rates_to_public_rates(rates: list):
if rates is None:
return None
Expand Down
34 changes: 17 additions & 17 deletions tests/unit/utils/test_get_off_peak_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,58 +37,58 @@ async def test_when_rates_spead_over_two_days_then_off_peak_cost_not_retrieved()
assert result is None

@pytest.mark.asyncio
async def test_bob():
async def test_when_rates_available_then_off_peak_cost_returned():
period_from = datetime.strptime("2023-11-04T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z")
period_to = datetime.strptime("2023-11-06T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z")
current = datetime.strptime("2023-11-05T10:00:01Z", "%Y-%m-%dT%H:%M:%S%z")
data = [
{
"value_exc_vat": 28.8068,
"value_inc_vat": 30.24714,
"start": "2023-11-06T04:30:00Z",
"end": "2023-11-07T00:30:00Z"
"valid_from": "2023-11-06T04:30:00Z",
"valid_to": "2023-11-07T00:30:00Z"
},
{
"value_exc_vat": 8.5714,
"value_inc_vat": 8.99997,
"start": "2023-11-06T00:30:00Z",
"end": "2023-11-06T04:30:00Z"
"valid_from": "2023-11-06T00:30:00Z",
"valid_to": "2023-11-06T04:30:00Z"
},
{
"value_exc_vat": 28.8068,
"value_inc_vat": 30.24714,
"start": "2023-11-05T04:30:00Z",
"end": "2023-11-06T00:30:00Z"
"valid_from": "2023-11-05T04:30:00Z",
"valid_to": "2023-11-06T00:30:00Z"
},
{
"value_exc_vat": 8.5714,
"value_inc_vat": 8.99997,
"start": "2023-11-05T00:30:00Z",
"end": "2023-11-05T04:30:00Z"
"valid_from": "2023-11-05T00:30:00Z",
"valid_to": "2023-11-05T04:30:00Z"
},
{
"value_exc_vat": 28.8068,
"value_inc_vat": 30.24714,
"start": "2023-11-04T04:30:00Z",
"end": "2023-11-05T00:30:00Z"
"valid_from": "2023-11-04T04:30:00Z",
"valid_to": "2023-11-05T00:30:00Z"
},
{
"value_exc_vat": 8.5714,
"value_inc_vat": 8.99997,
"start": "2023-11-04T00:30:00Z",
"end": "2023-11-04T04:30:00Z"
"valid_from": "2023-11-04T00:30:00Z",
"valid_to": "2023-11-04T04:30:00Z"
},
{
"value_exc_vat": 28.8068,
"value_inc_vat": 30.24714,
"start": "2023-11-03T04:30:00Z",
"end": "2023-11-04T00:30:00Z"
"valid_from": "2023-11-03T04:30:00Z",
"valid_to": "2023-11-04T00:30:00Z"
}
]
rate_data = rates_to_thirty_minute_increments(data, period_from, period_to, 'tariff')
rate_data = rates_to_thirty_minute_increments({ "results": data }, period_from, period_to, 'tariff')

# Act
result = get_off_peak_cost(current, rate_data)

# Assert
assert result is None
assert result == 8.99997
Loading

0 comments on commit 8da4679

Please sign in to comment.