Skip to content

Commit 6ad8db1

Browse files
committed
feat: Added raising of target timeframe data source events (2 hours dev time)
1 parent b98db85 commit 6ad8db1

File tree

7 files changed

+110
-33
lines changed

7 files changed

+110
-33
lines changed

_docs/migrations/target_timeframes.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,33 @@ The first thing you need to do is install the new integration. Full instructions
1212

1313
Once installed, you'll need to configure the integration by setting up a data source that represents data coming from this integration. This can be done by [following the link](https://my.home-assistant.io/redirect/config_flow_start/?domain=target_timeframes) or navigating to your integrations view, clicking 'Add integration' and searching for 'Target Timeframes'. You'll need a data source for each of your meters you want to create target rate sensors for (e.g. one for import and one for export).
1414

15-
The recommended name is `Octopus Energy Import` and the recommended source id is `octopus_energy_import`, but you can pick whatever you want as long as it's unique within the integration.
15+
The recommended name is `Octopus Energy Import`.
16+
17+
The recommended source id will depend on if you're wanting to just consume the rates straight from this integration, or if you want the target timeframe sensors to also include other additional/external data (e.g. carbon intensity or free electricity sessions).
18+
19+
### I just want OE rate data
20+
21+
The source id should follow the following format `octopus_energy_<<METER MPAN OR MPRN>>_<<METER SERIAL NUMBER>>`, depending on which meter you want the rate information to come from. For example if you want your target timeframes to be powered by your import meter with an MPAN of `123` and serial number of `ABC`, then your data source id should be equal to `octopus_energy_123_ABC`.
22+
23+
Once rate information is retrieved by this integration, data should flow automatically into this data source. You can confirm this by looking at the [Data Source Last Updated entity](bottlecapdave.github.io/HomeAssistant-TargetTimeframes/setup/data_source/#data-source-last-updated).
24+
25+
### I want OE rate data as well as other data
26+
27+
The recommended source id is `octopus_energy_import`, but you can pick whatever you want as long as it's unique within the integration and not equal to `octopus_energy_<<METER MPAN OR MPRN>>_<<METER SERIAL NUMBER>>`
1628

1729
![Data Source window](../assets/target_timeframes_data_source.png)
1830

19-
## Configuring Octopus Energy data
31+
#### Configuring data
2032

2133
Next, we'll need to get data from the Octopus Energy integration into the Target Timeframes integration. The recommended approach is an automation based on one of the [available blueprints](https://bottlecapdave.github.io/HomeAssistant-TargetTimeframes/blueprints/#octopus-energy).
2234

2335
There are different blueprints available depending upon whether you want your target rate sensors to take account of just carbon intensity, just Octopus rates, or both. For target rate sensors that use Octopus rates there are different blueprints depending upon whether you want to take account of Octopus free electricity sessions or not.
2436

25-
Select the blueprint you want to use and click 'Install blueprint'. You will get a prompt to open a page in Home Assistant, click 'Open link', you'll get a second prompt to confirm you want to import the blueprint, click 'Preview blueprint' then 'Import blueprint' and the blueprint will be installed in your Home Assistant.
37+
Select the blueprint you want to use and click 'Install blueprint'. You will get a prompt to open a page in Home Assistant, click 'Open link', you'll get a second prompt to confirm you want to import the blueprint, click 'Preview blueprint' then 'Import blueprint' and the blueprint will be installed in your Home Assistant.
2638

27-
Next you need to create an automation using the blueprint you just imported. The automation will track when the rate entities within the Octopus Energy integration are updated and will then transform the rate data into the shape required by Target Timeframes and use the available service to add the rate data with the data source we just created. Each `value` in Target Timeframes will represent our rate in pounds/pence.
39+
Next you need to create an automation using the blueprint you just imported. The automation will track when the rate entities within the Octopus Energy integration are updated and will then transform the rate data into the shape required by Target Timeframes and use the available service to add the rate data with the data source we just created. Each `value` in Target Timeframes will represent our rate in pounds/pence.
2840

29-
Click the name of the blueprint you just imported. You'll be prompted to configure the blueprint with the names of your Octopus Integration sensors. Use the dropdowns to select the appropriate Home Assistant sensor or event name:
41+
Click the name of the blueprint you just imported. You'll be prompted to configure the blueprint with the names of your Octopus Integration sensors. Use the dropdowns to select the appropriate Home Assistant sensor or event name:
3042

3143
![Blueprint configuration](../assets/target_timeframes_blueprint.png)
3244

custom_components/octopus_energy/const.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@
151151
EVENT_NEW_FREE_ELECTRICITY_SESSION = "octopus_energy_new_octoplus_free_electricity_session"
152152
EVENT_ALL_FREE_ELECTRICITY_SESSIONS = "octopus_energy_all_octoplus_free_electricity_sessions"
153153

154+
EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE = "target_timeframe_update_data_source"
155+
EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE_ID = "octopus_energy_{}_{}"
156+
154157
REPAIR_UNIQUE_RATES_CHANGED_KEY = "electricity_unique_rates_updated_{}"
155158
REPAIR_INVALID_API_KEY = "invalid_api_key_{}"
156159
REPAIR_ACCOUNT_NOT_FOUND = "account_not_found_{}"

custom_components/octopus_energy/coordinators/__init__.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111

1212
from ..utils import (
1313
Tariff,
14-
get_active_tariff
14+
get_active_tariff,
15+
private_rates_to_target_timeframe_data
1516
)
1617
from ..utils.rate_information import get_min_max_average_rates
1718
from ..utils.requests import calculate_next_refresh
18-
from ..const import DOMAIN, REPAIR_TARIFF_RATES_EMPTY
19+
from ..const import DOMAIN, EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE, EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE_ID, REPAIR_TARIFF_RATES_EMPTY
1920
from ..utils.repairs import safe_repair_key
2021

2122
_LOGGER = logging.getLogger(__name__)
@@ -110,9 +111,15 @@ def raise_rate_events(current_datetime: datetime,
110111
(old_previous_rates, old_current_rates, old_next_rates) = __rates_to_current_previous_next_rates(previous_datetime, previous_rates)
111112
(new_previous_rates, new_current_rates, new_next_rates) = __rates_to_current_previous_next_rates(current_datetime, new_rates)
112113

113-
__raise_rate_event(previous_event_key, new_previous_rates, old_previous_rates, additional_attributes, fire_event)
114-
__raise_rate_event(current_event_key, new_current_rates, old_current_rates, additional_attributes, fire_event)
115-
__raise_rate_event(next_event_key, new_next_rates, old_next_rates, additional_attributes, fire_event)
114+
previous_event_raised = __raise_rate_event(previous_event_key, new_previous_rates, old_previous_rates, additional_attributes, fire_event)
115+
current_event_raised = __raise_rate_event(current_event_key, new_current_rates, old_current_rates, additional_attributes, fire_event)
116+
next_event_raised = __raise_rate_event(next_event_key, new_next_rates, old_next_rates, additional_attributes, fire_event)
117+
118+
if (previous_event_raised or current_event_raised or next_event_raised):
119+
fire_event(EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE, {
120+
"data_source_id": EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE_ID.format(additional_attributes["mpan"] if "mpan" in additional_attributes else additional_attributes["mprn"], additional_attributes["serial_number"]),
121+
"data": private_rates_to_target_timeframe_data(new_rates)
122+
})
116123

117124
def get_electricity_meter_tariff(current: datetime, account_info, target_mpan: str, target_serial_number: str):
118125
if len(account_info["electricity_meter_points"]) > 0:

custom_components/octopus_energy/utils/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,25 @@ def private_rates_to_public_rates(rates: list):
163163
new_rates.append(new_rate)
164164

165165
return new_rates
166+
167+
def private_rates_to_target_timeframe_data(rates: list):
168+
new_rates = []
169+
170+
for rate in rates:
171+
metadata = {}
172+
if "is_capped" in rate:
173+
metadata["is_capped"] = rate["is_capped"]
174+
175+
if "is_intelligent_adjusted" in rate:
176+
metadata["is_intelligent_adjusted"] = rate["is_intelligent_adjusted"]
177+
178+
new_rate = {
179+
"start": as_local(rate["start"]),
180+
"end": as_local(rate["end"]),
181+
"value": rate["value_inc_vat"],
182+
"metadata": metadata
183+
}
184+
185+
new_rates.append(new_rate)
186+
187+
return new_rates
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from custom_components.octopus_energy.const import EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE
2+
3+
4+
def assert_raised_target_timeframe_update_event(raised_events: dict, expected_rates: list, expected_serial_number: str, expected_mpan_or_mprn: str):
5+
assert EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE in raised_events
6+
assert "data_source_id" in raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]
7+
assert raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]["data_source_id"] == f"octopus_energy_{expected_mpan_or_mprn}_{expected_serial_number}"
8+
assert "data" in raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]
9+
assert len(raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]["data"]) == len(expected_rates)
10+
11+
for (index, rate) in enumerate(expected_rates):
12+
assert raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]["data"][index]["start"] == rate["start"]
13+
assert raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]["data"][index]["end"] == rate["end"]
14+
assert raised_events[EVENT_TARGET_TIMEFRAME_UPDATE_DATA_SOURCE]["data"][index]["value"] == round(rate["value_inc_vat"] / 100, 6)

0 commit comments

Comments
 (0)