Skip to content

Commit f1ebf1a

Browse files
Feat/intelligent changes (#1488)
2 parents f3f89fa + 2462dff commit f1ebf1a

File tree

4 files changed

+80
-45
lines changed

4 files changed

+80
-45
lines changed

_docs/blueprints/octopus_energy_manual_intelligent_refresh.yaml

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,59 @@ variables:
5555
millisecond_jitter: >
5656
{{ range(1, 1000) | random }}
5757
58-
mode: queued
59-
max: 4
58+
mode: single
6059
triggers:
6160
- trigger: state
6261
id: car_plugged_in
6362
entity_id: !input car_plugged_in_sensor
6463
to: !input car_plugged_in_sensor_state
64+
- trigger: state
65+
id: car_unplugged
66+
entity_id: !input car_plugged_in_sensor
67+
from: !input car_plugged_in_sensor_state
68+
not_to: !input car_plugged_in_sensor_state
6569
- trigger: time_pattern
70+
id: periodic_check
6671
minutes: "/1"
6772
conditions:
68-
- condition: state
69-
entity_id: !input car_plugged_in_sensor
70-
state: !input car_plugged_in_sensor_state
71-
# Make sure that our dispatches are either due to be updated or our automation was triggered due to the vehicle being plugged in
7273
- condition: or
7374
conditions:
75+
- condition: and
76+
conditions:
77+
- condition: state
78+
entity_id: !input car_plugged_in_sensor
79+
state: !input car_plugged_in_sensor_state
80+
# Make sure that our dispatches are either due to be updated or our automation was triggered due to the vehicle being plugged in
81+
- condition: or
82+
conditions:
83+
- condition: template
84+
value_template: >
85+
{{ trigger.id == "car_plugged_in" }}
86+
- condition: template
87+
value_template: >
88+
{% set next_refresh = state_attr(intelligent_dispatches_data_last_retrieved_sensor, 'next_refresh') %}
89+
{{ next_refresh == None or next_refresh | as_datetime | as_local < now() }}
7490
- condition: template
7591
value_template: >
76-
{{ trigger.id == "car_plugged_in" }}
92+
{{ trigger.id == "car_unplugged" }}
93+
actions:
94+
# Wait 30 seconds to give OE a chance to update the dispatches if caused by car state change
95+
- if:
7796
- condition: template
7897
value_template: >
79-
{{ state_attr(intelligent_dispatches_data_last_retrieved_sensor, 'next_refresh') | as_datetime | as_local < now() }}
80-
actions:
81-
# Wait 30 seconds to give OE a chance to update the dispatches
82-
- delay: 00:00:30
98+
{{ trigger.id != "periodic_check" }}
99+
then:
100+
- delay: 00:00:30
101+
# Wait until we are under the request limit
102+
- wait_template: >-
103+
{% set requests_current_hour = state_attr(intelligent_dispatches_data_last_retrieved_sensor, 'requests_current_hour') %}
104+
{% set maximum_requests_per_hour = state_attr(intelligent_dispatches_data_last_retrieved_sensor, 'maximum_requests_per_hour') %}
105+
{% set request_limits_last_reset = state_attr(intelligent_dispatches_data_last_retrieved_sensor, 'request_limits_last_reset') %}
106+
{{ requests_current_hour == None or
107+
(requests_current_hour | int < maximum_requests_per_hour | int) or
108+
request_limits_last_reset + timedelta(hours=1) < now()
109+
}}
110+
continue_on_timeout: true
83111
# Add a bit of jitter so the API isn't hit at once
84112
- delay:
85113
milliseconds: >

_docs/entities/diagnostics.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ This sensor states when intelligent dispatches data was last retrieved.
7676
| `attempts` | `integer` | The number of attempts that have been made to retrieve the data |
7777
| `next_refresh` | `datetime` | The timestamp of when the data will next be attempted to be retrieved |
7878
| `last_error` | `string` | The error that was raised to cause the last retrieval attempt to fail |
79+
| `requests_current_hour` | `integer` | The number of requests that have been made during the current hour. The start of the hour starts when the first request is made. |
80+
| `maximum_requests_per_hour` | `integer` | The maximum number of requests that can be made during an hour. The start of the hour starts when the first request is made. |
81+
| `request_limits_last_reset` | `datetime` | The datetime when the request limits were last reset. This will reset when a request is made and is within the designated limits. |
7982

8083
## Intelligent Settings Data Last Retrieved
8184

custom_components/octopus_energy/coordinators/intelligent_dispatches.py

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
_LOGGER = logging.getLogger(__name__)
3535

36-
MAXIMUM_RATES_PER_HOUR = 20
36+
MAXIMUM_DISPATCH_REQUESTS_PER_HOUR = 20
3737

3838
class IntelligentDispatchDataUpdateCoordinator(DataUpdateCoordinator):
3939

@@ -145,43 +145,46 @@ async def async_retrieve_intelligent_dispatches(
145145
is_manual_refresh: bool,
146146
planned_dispatches_supported: bool,
147147
):
148-
requests_current_hour = existing_intelligent_dispatches_result.requests_current_hour if existing_intelligent_dispatches_result is not None else 0
149-
requests_last_reset = existing_intelligent_dispatches_result.requests_current_hour_last_reset if existing_intelligent_dispatches_result is not None else current
150-
151-
if current - requests_last_reset >= timedelta(hours=1):
152-
requests_current_hour = 0
153-
requests_last_reset = current
154-
155-
if requests_current_hour >= MAXIMUM_RATES_PER_HOUR:
156-
_LOGGER.debug('Maximum requests reached for current hour')
157-
return IntelligentDispatchesCoordinatorResult(
158-
existing_intelligent_dispatches_result.last_evaluated,
159-
existing_intelligent_dispatches_result.request_attempts,
160-
existing_intelligent_dispatches_result.dispatches,
161-
existing_intelligent_dispatches_result.requests_current_hour,
162-
existing_intelligent_dispatches_result.requests_current_hour_last_reset,
163-
last_error=f"Maximum requests of {MAXIMUM_RATES_PER_HOUR}/hour reached. Will reset after {requests_last_reset + timedelta(hours=1)}"
164-
)
165-
166-
# We don't want manual refreshing to occur too many times
167-
if (is_manual_refresh and
168-
existing_intelligent_dispatches_result is not None and
169-
(existing_intelligent_dispatches_result.last_retrieved + timedelta(minutes=1)) > current):
170-
_LOGGER.debug('Maximum requests reached for current hour')
171-
return IntelligentDispatchesCoordinatorResult(
172-
existing_intelligent_dispatches_result.last_evaluated,
173-
existing_intelligent_dispatches_result.request_attempts,
174-
existing_intelligent_dispatches_result.dispatches,
175-
existing_intelligent_dispatches_result.requests_current_hour,
176-
existing_intelligent_dispatches_result.requests_current_hour_last_reset,
177-
last_error=f"Manual refreshing of dispatches cannot be be called again until {existing_intelligent_dispatches_result.last_retrieved + timedelta(minutes=1)}"
178-
)
179-
180148
if (account_info is not None):
181149
account_id = account_info["id"]
182150
if (existing_intelligent_dispatches_result is None or
183151
current >= existing_intelligent_dispatches_result.next_refresh or
184152
is_manual_refresh):
153+
154+
requests_current_hour = existing_intelligent_dispatches_result.requests_current_hour if existing_intelligent_dispatches_result is not None else 0
155+
requests_last_reset = existing_intelligent_dispatches_result.requests_current_hour_last_reset if existing_intelligent_dispatches_result is not None else current
156+
157+
if current - requests_last_reset >= timedelta(hours=1):
158+
requests_current_hour = 0
159+
requests_last_reset = current
160+
161+
if requests_current_hour >= MAXIMUM_DISPATCH_REQUESTS_PER_HOUR:
162+
error = f"Maximum requests of {MAXIMUM_DISPATCH_REQUESTS_PER_HOUR}/hour reached. Will reset after {requests_last_reset + timedelta(hours=1)}"
163+
_LOGGER.debug(error)
164+
return IntelligentDispatchesCoordinatorResult(
165+
existing_intelligent_dispatches_result.last_evaluated,
166+
existing_intelligent_dispatches_result.request_attempts,
167+
existing_intelligent_dispatches_result.dispatches,
168+
existing_intelligent_dispatches_result.requests_current_hour,
169+
existing_intelligent_dispatches_result.requests_current_hour_last_reset,
170+
last_error=error
171+
)
172+
173+
# We don't want manual refreshing to occur too many times
174+
if (is_manual_refresh and
175+
existing_intelligent_dispatches_result is not None and
176+
(existing_intelligent_dispatches_result.last_retrieved + timedelta(minutes=1)) > current):
177+
error = f"Manual refreshing of dispatches cannot be be called again until {existing_intelligent_dispatches_result.last_retrieved + timedelta(minutes=1)}"
178+
_LOGGER.debug(error)
179+
return IntelligentDispatchesCoordinatorResult(
180+
existing_intelligent_dispatches_result.last_evaluated,
181+
existing_intelligent_dispatches_result.request_attempts,
182+
existing_intelligent_dispatches_result.dispatches,
183+
existing_intelligent_dispatches_result.requests_current_hour,
184+
existing_intelligent_dispatches_result.requests_current_hour_last_reset,
185+
last_error=error
186+
)
187+
185188
dispatches = None
186189
raised_exception = None
187190
if has_intelligent_tariff(current, account_info) and intelligent_device is not None:

custom_components/octopus_energy/diagnostics_entities/intelligent_dispatches_data_last_retrieved.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
)
66

77
from ..utils.error import exception_to_string
8-
from ..coordinators.intelligent_dispatches import IntelligentDispatchesCoordinatorResult
8+
from ..coordinators.intelligent_dispatches import MAXIMUM_DISPATCH_REQUESTS_PER_HOUR, IntelligentDispatchesCoordinatorResult
99
from .base import OctopusEnergyBaseDataLastRetrieved
1010

1111
class OctopusEnergyIntelligentDispatchesDataLastRetrieved(OctopusEnergyBaseDataLastRetrieved):
@@ -37,6 +37,7 @@ def _handle_coordinator_update(self) -> None:
3737
"next_refresh": result.next_refresh if result is not None else None,
3838
"last_error": exception_to_string(result.last_error) if result is not None else None,
3939
"requests_current_hour": result.requests_current_hour if result is not None else None,
40+
"maximum_requests_per_hour": MAXIMUM_DISPATCH_REQUESTS_PER_HOUR,
4041
"request_limits_last_reset": result.requests_current_hour_last_reset if result is not None else None
4142
}
4243

0 commit comments

Comments
 (0)