2828from ..api_client .intelligent_device import IntelligentDevice
2929from ..storage .intelligent_dispatches import async_save_cached_intelligent_dispatches
3030
31- from ..intelligent import clean_previous_dispatches , has_intelligent_tariff , mock_intelligent_dispatches
31+ from ..intelligent import clean_intelligent_dispatch_history , clean_previous_dispatches , has_dispatches_changed , has_intelligent_tariff , mock_intelligent_dispatches
3232from ..coordinators .intelligent_device import IntelligentDeviceCoordinatorResult
33+ from ..storage .intelligent_dispatches_history import IntelligentDispatchesHistory , async_save_cached_intelligent_dispatches_history
3334
3435_LOGGER = logging .getLogger (__name__ )
3536
@@ -71,38 +72,17 @@ async def refresh_dispatches(self):
7172
7273class IntelligentDispatchesCoordinatorResult (BaseCoordinatorResult ):
7374 dispatches : IntelligentDispatches
75+ history : IntelligentDispatchesHistory
7476 requests_current_hour : int
7577 requests_current_hour_last_reset : datetime
7678
77- def __init__ (self , last_evaluated : datetime , request_attempts : int , dispatches : IntelligentDispatches , requests_current_hour : int , requests_current_hour_last_reset : datetime , last_error : Exception | None = None ):
79+ def __init__ (self , last_evaluated : datetime , request_attempts : int , dispatches : IntelligentDispatches , history : IntelligentDispatchesHistory , requests_current_hour : int , requests_current_hour_last_reset : datetime , last_error : Exception | None = None ):
7880 super ().__init__ (last_evaluated , request_attempts , REFRESH_RATE_IN_MINUTES_INTELLIGENT , None , last_error )
7981 self .dispatches = dispatches
82+ self .history = history
8083 self .requests_current_hour = requests_current_hour
8184 self .requests_current_hour_last_reset = requests_current_hour_last_reset
8285
83- def has_dispatch_items_changed (existing_dispatches : list [SimpleIntelligentDispatchItem ], new_dispatches : list [SimpleIntelligentDispatchItem ]):
84- if len (existing_dispatches ) != len (new_dispatches ):
85- return True
86-
87- if len (existing_dispatches ) > 0 :
88- for i in range (0 , len (existing_dispatches )):
89- if (existing_dispatches [i ].start != new_dispatches [i ].start or
90- existing_dispatches [i ].end != new_dispatches [i ].end ):
91- return True
92-
93- return False
94-
95- def has_dispatches_changed (existing_dispatches : IntelligentDispatches , new_dispatches : IntelligentDispatches ):
96- return (
97- existing_dispatches .current_state != new_dispatches .current_state or
98- len (existing_dispatches .completed ) != len (new_dispatches .completed ) or
99- has_dispatch_items_changed (existing_dispatches .completed , new_dispatches .completed ) or
100- len (existing_dispatches .planned ) != len (new_dispatches .planned ) or
101- has_dispatch_items_changed (existing_dispatches .planned , new_dispatches .planned ) or
102- len (existing_dispatches .started ) != len (new_dispatches .started ) or
103- has_dispatch_items_changed (existing_dispatches .started , new_dispatches .started )
104- )
105-
10686def merge_started_dispatches (current : datetime ,
10787 current_state : str ,
10888 started_dispatches : list [SimpleIntelligentDispatchItem ],
@@ -165,6 +145,7 @@ async def async_retrieve_intelligent_dispatches(
165145 existing_intelligent_dispatches_result .last_evaluated ,
166146 existing_intelligent_dispatches_result .request_attempts ,
167147 existing_intelligent_dispatches_result .dispatches ,
148+ existing_intelligent_dispatches_result .history ,
168149 existing_intelligent_dispatches_result .requests_current_hour ,
169150 existing_intelligent_dispatches_result .requests_current_hour_last_reset ,
170151 last_error = error
@@ -180,6 +161,7 @@ async def async_retrieve_intelligent_dispatches(
180161 existing_intelligent_dispatches_result .last_evaluated ,
181162 existing_intelligent_dispatches_result .request_attempts ,
182163 existing_intelligent_dispatches_result .dispatches ,
164+ existing_intelligent_dispatches_result .history ,
183165 existing_intelligent_dispatches_result .requests_current_hour ,
184166 existing_intelligent_dispatches_result .requests_current_hour_last_reset ,
185167 last_error = error
@@ -216,15 +198,20 @@ async def async_retrieve_intelligent_dispatches(
216198
217199 dispatches .completed = clean_previous_dispatches (current ,
218200 (existing_intelligent_dispatches_result .dispatches .completed if existing_intelligent_dispatches_result is not None and existing_intelligent_dispatches_result .dispatches is not None and existing_intelligent_dispatches_result .dispatches .completed is not None else []) + dispatches .completed )
201+
202+ new_history = clean_intelligent_dispatch_history (current ,
203+ dispatches ,
204+ existing_intelligent_dispatches_result .history .history if existing_intelligent_dispatches_result is not None else [])
219205
220- return IntelligentDispatchesCoordinatorResult (current , 1 , dispatches , requests_current_hour + 1 , requests_last_reset )
206+ return IntelligentDispatchesCoordinatorResult (current , 1 , dispatches , IntelligentDispatchesHistory ( new_history ), requests_current_hour + 1 , requests_last_reset )
221207
222208 result = None
223209 if (existing_intelligent_dispatches_result is not None ):
224210 result = IntelligentDispatchesCoordinatorResult (
225211 existing_intelligent_dispatches_result .last_evaluated ,
226212 existing_intelligent_dispatches_result .request_attempts + 1 ,
227213 existing_intelligent_dispatches_result .dispatches ,
214+ existing_intelligent_dispatches_result .history ,
228215 existing_intelligent_dispatches_result .requests_current_hour + 1 ,
229216 existing_intelligent_dispatches_result .requests_current_hour_last_reset ,
230217 last_error = raised_exception
@@ -234,7 +221,15 @@ async def async_retrieve_intelligent_dispatches(
234221 _LOGGER .warning (f"Failed to retrieve new dispatches - using cached dispatches. See diagnostics sensor for more information." )
235222 else :
236223 # We want to force into our fallback mode
237- result = IntelligentDispatchesCoordinatorResult (current - timedelta (minutes = REFRESH_RATE_IN_MINUTES_INTELLIGENT ), 2 , None , requests_current_hour , requests_last_reset , last_error = raised_exception )
224+ result = IntelligentDispatchesCoordinatorResult (
225+ current - timedelta (minutes = REFRESH_RATE_IN_MINUTES_INTELLIGENT ),
226+ 2 ,
227+ None ,
228+ IntelligentDispatchesHistory ([]),
229+ requests_current_hour ,
230+ requests_last_reset ,
231+ last_error = raised_exception
232+ )
238233 _LOGGER .warning (f"Failed to retrieve new dispatches. See diagnostics sensor for more information." )
239234
240235 return result
@@ -253,6 +248,7 @@ async def async_refresh_intelligent_dispatches(
253248 is_manual_refresh : bool ,
254249 planned_dispatches_supported : bool ,
255250 async_save_dispatches : Callable [[IntelligentDispatches ], Awaitable [list ]],
251+ async_save_dispatches_history : Callable [[IntelligentDispatchesHistory ], Awaitable [list ]],
256252):
257253 result = await async_retrieve_intelligent_dispatches (
258254 current ,
@@ -282,10 +278,17 @@ async def async_refresh_intelligent_dispatches(
282278 existing_intelligent_dispatches_result .dispatches is None or
283279 has_dispatches_changed (existing_intelligent_dispatches_result .dispatches , result .dispatches )):
284280 await async_save_dispatches (result .dispatches )
281+ await async_save_dispatches_history (result .history )
285282
286283 return result
287284
288- async def async_setup_intelligent_dispatches_coordinator (hass , account_id : str , device_id : str , mock_intelligent_data : bool , manual_dispatch_refreshes : bool , planned_dispatches_supported : bool ):
285+ async def async_setup_intelligent_dispatches_coordinator (
286+ hass ,
287+ account_id : str ,
288+ device_id : str ,
289+ mock_intelligent_data : bool ,
290+ manual_dispatch_refreshes : bool ,
291+ planned_dispatches_supported : bool ):
289292 async def async_update_intelligent_dispatches_data (is_manual_refresh = False ):
290293 """Fetch data from API endpoint."""
291294 # Request our account data to be refreshed
@@ -304,17 +307,22 @@ async def async_update_intelligent_dispatches_data(is_manual_refresh = False):
304307 client : OctopusEnergyApiClient = hass .data [DOMAIN ][account_id ][DATA_CLIENT ]
305308 account_result = hass .data [DOMAIN ][account_id ][DATA_ACCOUNT ]
306309 account_info = account_result .account if account_result is not None else None
310+ existing_intelligent_dispatches_result = (hass .data [DOMAIN ][account_id ][DATA_INTELLIGENT_DISPATCHES ][device_id ]
311+ if DATA_INTELLIGENT_DISPATCHES in hass .data [DOMAIN ][account_id ] and
312+ device_id in hass .data [DOMAIN ][account_id ][DATA_INTELLIGENT_DISPATCHES ]
313+ else None )
307314
308315 hass .data [DOMAIN ][account_id ][DATA_INTELLIGENT_DISPATCHES ][device_id ] = await async_refresh_intelligent_dispatches (
309316 current ,
310317 client ,
311318 account_info ,
312319 intelligent_device ,
313- hass . data [ DOMAIN ][ account_id ][ DATA_INTELLIGENT_DISPATCHES ][ device_id ] if DATA_INTELLIGENT_DISPATCHES in hass . data [ DOMAIN ][ account_id ] and device_id in hass . data [ DOMAIN ][ account_id ][ DATA_INTELLIGENT_DISPATCHES ] else None ,
320+ existing_intelligent_dispatches_result ,
314321 mock_intelligent_data ,
315322 is_manual_refresh ,
316323 planned_dispatches_supported ,
317- lambda dispatches : async_save_cached_intelligent_dispatches (hass , device_id , dispatches )
324+ lambda dispatches : async_save_cached_intelligent_dispatches (hass , device_id , dispatches ),
325+ lambda history : async_save_cached_intelligent_dispatches_history (hass , device_id , history )
318326 )
319327
320328 return hass .data [DOMAIN ][account_id ][DATA_INTELLIGENT_DISPATCHES ][device_id ]
0 commit comments