mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Make renault scan interval dynamic (#142964)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
parent
27b7fb6f91
commit
c422bcf1e2
@ -7,7 +7,9 @@ DOMAIN = "renault"
|
||||
CONF_LOCALE = "locale"
|
||||
CONF_KAMEREON_ACCOUNT_ID = "kamereon_account_id"
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = 420 # 7 minutes
|
||||
# normal number of allowed calls per hour to the API
|
||||
# for a single car and the 7 coordinator, it is a scan every 7mn
|
||||
MAX_CALLS_PER_HOURS = 60
|
||||
|
||||
# If throttled time to pause the updates, in seconds
|
||||
COOLING_UPDATES_SECONDS = 60 * 15 # 15 minutes
|
||||
|
@ -32,9 +32,9 @@ from time import time
|
||||
from .const import (
|
||||
CONF_KAMEREON_ACCOUNT_ID,
|
||||
COOLING_UPDATES_SECONDS,
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
MAX_CALLS_PER_HOURS,
|
||||
)
|
||||
from .renault_vehicle import RenaultVehicleProxy
|
||||
from .renault_vehicle import COORDINATORS, RenaultVehicleProxy
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -82,7 +82,6 @@ class RenaultHub:
|
||||
async def async_initialise(self, config_entry: RenaultConfigEntry) -> None:
|
||||
"""Set up proxy."""
|
||||
account_id: str = config_entry.data[CONF_KAMEREON_ACCOUNT_ID]
|
||||
scan_interval = timedelta(seconds=DEFAULT_SCAN_INTERVAL)
|
||||
|
||||
self._account = await self._client.get_api_account(account_id)
|
||||
vehicles = await self._account.get_vehicles()
|
||||
@ -94,6 +93,12 @@ class RenaultHub:
|
||||
raise ConfigEntryNotReady(
|
||||
"Failed to retrieve vehicle details from Renault servers"
|
||||
)
|
||||
|
||||
num_call_per_scan = len(COORDINATORS) * len(vehicles.vehicleLinks)
|
||||
scan_interval = timedelta(
|
||||
seconds=(3600 * num_call_per_scan) / MAX_CALLS_PER_HOURS
|
||||
)
|
||||
|
||||
device_registry = dr.async_get(self._hass)
|
||||
await asyncio.gather(
|
||||
*(
|
||||
@ -108,6 +113,21 @@ class RenaultHub:
|
||||
)
|
||||
)
|
||||
|
||||
# all vehicles have been initiated with the right number of active coordinators
|
||||
num_call_per_scan = 0
|
||||
for vehicle_link in vehicles.vehicleLinks:
|
||||
vehicle = self._vehicles[str(vehicle_link.vin)]
|
||||
num_call_per_scan += len(vehicle.coordinators)
|
||||
|
||||
new_scan_interval = timedelta(
|
||||
seconds=(3600 * num_call_per_scan) / MAX_CALLS_PER_HOURS
|
||||
)
|
||||
if new_scan_interval != scan_interval:
|
||||
# we need to change the vehicles with the right scan interval
|
||||
for vehicle_link in vehicles.vehicleLinks:
|
||||
vehicle = self._vehicles[str(vehicle_link.vin)]
|
||||
vehicle.update_scan_interval(new_scan_interval)
|
||||
|
||||
async def async_initialise_vehicle(
|
||||
self,
|
||||
vehicle_link: KamereonVehiclesLink,
|
||||
|
@ -91,6 +91,13 @@ class RenaultVehicleProxy:
|
||||
self._scan_interval = scan_interval
|
||||
self._hub = hub
|
||||
|
||||
def update_scan_interval(self, scan_interval: timedelta) -> None:
|
||||
"""Set the scan interval for the vehicle."""
|
||||
if scan_interval != self._scan_interval:
|
||||
self._scan_interval = scan_interval
|
||||
for coordinator in self.coordinators.values():
|
||||
coordinator.update_interval = scan_interval
|
||||
|
||||
@property
|
||||
def details(self) -> models.KamereonVehicleDetails:
|
||||
"""Return the specs of the vehicle."""
|
||||
|
291
tests/components/renault/fixtures/vehicle_multi.json
Normal file
291
tests/components/renault/fixtures/vehicle_multi.json
Normal file
@ -0,0 +1,291 @@
|
||||
{
|
||||
"accountId": "account-id-2",
|
||||
"country": "IT",
|
||||
"vehicleLinks": [
|
||||
{
|
||||
"brand": "RENAULT",
|
||||
"vin": "VF1AAAAA555777999",
|
||||
"status": "ACTIVE",
|
||||
"linkType": "OWNER",
|
||||
"garageBrand": "RENAULT",
|
||||
"annualMileage": 16000,
|
||||
"mileage": 26464,
|
||||
"startDate": "2017-08-07",
|
||||
"createdDate": "2019-05-23T21:38:16.409008Z",
|
||||
"lastModifiedDate": "2020-11-17T08:41:40.497400Z",
|
||||
"ownershipStartDate": "2017-08-01",
|
||||
"cancellationReason": {},
|
||||
"connectedDriver": {
|
||||
"role": "MAIN_DRIVER",
|
||||
"createdDate": "2019-06-17T09:49:06.880627Z",
|
||||
"lastModifiedDate": "2019-06-17T09:49:06.880627Z"
|
||||
},
|
||||
"vehicleDetails": {
|
||||
"vin": "VF1AAAAA555777999",
|
||||
"registrationDate": "2017-08-01",
|
||||
"firstRegistrationDate": "2017-08-01",
|
||||
"engineType": "5AQ",
|
||||
"engineRatio": "601",
|
||||
"modelSCR": "ZOE",
|
||||
"deliveryCountry": {
|
||||
"code": "FR",
|
||||
"label": "FRANCE"
|
||||
},
|
||||
"family": {
|
||||
"code": "X10",
|
||||
"label": "FAMILLE X10",
|
||||
"group": "007"
|
||||
},
|
||||
"tcu": {
|
||||
"code": "TCU0G2",
|
||||
"label": "TCU VER 0 GEN 2",
|
||||
"group": "E70"
|
||||
},
|
||||
"navigationAssistanceLevel": {
|
||||
"code": "NAV3G5",
|
||||
"label": "LEVEL 3 TYPE 5 NAVIGATION",
|
||||
"group": "408"
|
||||
},
|
||||
"battery": {
|
||||
"code": "BT4AR1",
|
||||
"label": "BATTERIE BT4AR1",
|
||||
"group": "968"
|
||||
},
|
||||
"radioType": {
|
||||
"code": "RAD37A",
|
||||
"label": "RADIO 37A",
|
||||
"group": "425"
|
||||
},
|
||||
"registrationCountry": {
|
||||
"code": "FR"
|
||||
},
|
||||
"brand": {
|
||||
"label": "RENAULT"
|
||||
},
|
||||
"model": {
|
||||
"code": "X101VE",
|
||||
"label": "ZOE",
|
||||
"group": "971"
|
||||
},
|
||||
"gearbox": {
|
||||
"code": "BVEL",
|
||||
"label": "BOITE A VARIATEUR ELECTRIQUE",
|
||||
"group": "427"
|
||||
},
|
||||
"version": {
|
||||
"code": "INT MB 10R"
|
||||
},
|
||||
"energy": {
|
||||
"code": "ELEC",
|
||||
"label": "ELECTRIQUE",
|
||||
"group": "019"
|
||||
},
|
||||
"registrationNumber": "REG-NUMBER",
|
||||
"vcd": "SYTINC/SKTPOU/SAND41/FDIU1/SSESM/MAPSUP/SSCALL/SAND88/SAND90/SQKDRO/SDIFPA/FACBA2/PRLEX1/SSRCAR/CABDO2/TCU0G2/SWALBO/EVTEC1/STANDA/X10/B10/EA2/MB/ELEC/DG/TEMP/TR4X2/RV/ABS/CAREG/LAC/VT003/CPE/RET03/SPROJA/RALU16/CEAVRH/AIRBA1/SERIE/DRA/DRAP08/HARM02/ATAR/TERQG/SFBANA/KM/DPRPN/AVREPL/SSDECA/ASRESP/RDAR02/ALEVA/CACBL2/SOP02C/CTHAB2/TRNOR/LVAVIP/LVAREL/SASURV/KTGREP/SGSCHA/APL03/ALOUCC/CMAR3P/NAV3G5/RAD37A/BVEL/AUTAUG/RNORM/ISOFIX/EQPEUR/HRGM01/SDPCLV/TLFRAN/SPRODI/SAN613/SSAPEX/GENEV1/ELC1/SANCML/PE2012/PHAS1/SAN913/045KWH/BT4AR1/VEC153/X101VE/NBT017/5AQ",
|
||||
"assets": [
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv2.renault.com/ImageFromBookmark?configuration=SKTPOU%2FPRLEX1%2FSTANDA%2FB10%2FEA2%2FDG%2FVT003%2FRET03%2FRALU16%2FDRAP08%2FHARM02%2FTERQG%2FRDAR02%2FALEVA%2FSOP02C%2FTRNOR%2FLVAVIP%2FLVAREL%2FNAV3G5%2FRAD37A%2FSDPCLV%2FTLFRAN%2FGENEV1%2FSAN913%2FBT4AR1%2FNBT017&databaseId=1d514feb-93a6-4b45-8785-e11d2a6f1864&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv2.renault.com/ImageFromBookmark?configuration=SKTPOU%2FPRLEX1%2FSTANDA%2FB10%2FEA2%2FDG%2FVT003%2FRET03%2FRALU16%2FDRAP08%2FHARM02%2FTERQG%2FRDAR02%2FALEVA%2FSOP02C%2FTRNOR%2FLVAVIP%2FLVAREL%2FNAV3G5%2FRAD37A%2FSDPCLV%2FTLFRAN%2FGENEV1%2FSAN913%2FBT4AR1%2FNBT017&databaseId=1d514feb-93a6-4b45-8785-e11d2a6f1864&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "PDF",
|
||||
"assetRole": "GUIDE",
|
||||
"title": "PDF Guide",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "https://cdn.group.renault.com/ren/gb/myr/assets/x101ve/manual.pdf.asset.pdf/1558704861676.pdf"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "URL",
|
||||
"assetRole": "GUIDE",
|
||||
"title": "e-guide",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "http://gb.e-guide.renault.com/eng/Zoe"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "VIDEO",
|
||||
"assetRole": "CAR",
|
||||
"title": "10 Fundamentals about getting the best out of your electric vehicle",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "39r6QEKcOM4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "VIDEO",
|
||||
"assetRole": "CAR",
|
||||
"title": "Automatic Climate Control",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "Va2FnZFo_GE"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "URL",
|
||||
"assetRole": "CAR",
|
||||
"title": "More videos",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "https://www.youtube.com/watch?v=wfpCMkK1rKI"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "VIDEO",
|
||||
"assetRole": "CAR",
|
||||
"title": "Charging the battery",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "RaEad8DjUJs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assetType": "VIDEO",
|
||||
"assetRole": "CAR",
|
||||
"title": "Charging the battery at a station with a flap",
|
||||
"description": "",
|
||||
"renditions": [
|
||||
{
|
||||
"url": "zJfd7fJWtr0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"yearsOfMaintenance": 12,
|
||||
"connectivityTechnology": "RLINK1",
|
||||
"easyConnectStore": false,
|
||||
"electrical": true,
|
||||
"rlinkStore": false,
|
||||
"deliveryDate": "2017-08-11",
|
||||
"retrievedFromDhs": false,
|
||||
"engineEnergyType": "ELEC",
|
||||
"radioCode": "1234"
|
||||
}
|
||||
},
|
||||
{
|
||||
"brand": "RENAULT",
|
||||
"vin": "VF1AAAAA555777123",
|
||||
"status": "ACTIVE",
|
||||
"linkType": "USER",
|
||||
"garageBrand": "RENAULT",
|
||||
"mileage": 346,
|
||||
"startDate": "2020-06-12",
|
||||
"createdDate": "2020-06-12T15:02:00.555432Z",
|
||||
"lastModifiedDate": "2020-06-15T06:21:43.762467Z",
|
||||
"cancellationReason": {},
|
||||
"connectedDriver": {
|
||||
"role": "MAIN_DRIVER",
|
||||
"createdDate": "2020-06-15T06:20:39.107794Z",
|
||||
"lastModifiedDate": "2020-06-15T06:20:39.107794Z"
|
||||
},
|
||||
"vehicleDetails": {
|
||||
"vin": "VF1AAAAA555777123",
|
||||
"engineType": "H5H",
|
||||
"engineRatio": "470",
|
||||
"modelSCR": "CP1",
|
||||
"deliveryCountry": {
|
||||
"code": "BE",
|
||||
"label": "BELGIQUE"
|
||||
},
|
||||
"family": {
|
||||
"code": "XJB",
|
||||
"label": "FAMILLE B+X OVER",
|
||||
"group": "007"
|
||||
},
|
||||
"tcu": {
|
||||
"code": "AIVCT",
|
||||
"label": "AVEC BOITIER CONNECT AIVC",
|
||||
"group": "E70"
|
||||
},
|
||||
"navigationAssistanceLevel": {
|
||||
"code": "",
|
||||
"label": "",
|
||||
"group": ""
|
||||
},
|
||||
"battery": {
|
||||
"code": "SANBAT",
|
||||
"label": "SANS BATTERIE",
|
||||
"group": "968"
|
||||
},
|
||||
"radioType": {
|
||||
"code": "NA406",
|
||||
"label": "A-IVIMINDL, 2BO + 2BI + 2T, MICRO-DOUBLE, FM1/DAB+FM2",
|
||||
"group": "425"
|
||||
},
|
||||
"registrationCountry": {
|
||||
"code": "BE"
|
||||
},
|
||||
"brand": {
|
||||
"label": "RENAULT"
|
||||
},
|
||||
"model": {
|
||||
"code": "XJB1SU",
|
||||
"label": "CAPTUR II",
|
||||
"group": "971"
|
||||
},
|
||||
"gearbox": {
|
||||
"code": "BVA7",
|
||||
"label": "BOITE DE VITESSE AUTOMATIQUE 7 RAPPORTS",
|
||||
"group": "427"
|
||||
},
|
||||
"version": {
|
||||
"code": "ITAMFHA 6TH"
|
||||
},
|
||||
"energy": {
|
||||
"code": "ESS",
|
||||
"label": "ESSENCE",
|
||||
"group": "019"
|
||||
},
|
||||
"registrationNumber": "REG-NUMBER",
|
||||
"vcd": "ADR00/DLIGM2/PGPRT2/FEUAR3/CDVIT1/SKTPOU/SKTPGR/SSCCPC/SSPREM/FDIU2/MAPSTD/RCALL/MET04/DANGMO/ECOMOD/SSRCAR/AIVCT/AVGSI/TPRPE/TSGNE/2TON/ITPK7/MLEXP1/SPERTA/SSPERG/SPERTP/VOLCHA/SREACT/AVOSP1/SWALBO/DWGE01/AVC1A/1234Y/AEBS07/PRAHL/AVCAM/STANDA/XJB/HJB/EA3/MF/ESS/DG/TEMP/TR4X2/AFURGE/RVDIST/ABS/SBARTO/CA02/TOPAN/PBNCH/LAC/VSTLAR/CPE/RET04/2RVLG/RALU17/CEAVRH/AIRBA2/SERIE/DRA/DRAP05/HARM01/ATAR03/SGAV02/SGAR02/BIXPE/BANAL/KM/TPRM3/AVREPL/SSDECA/SFIRBA/ABLAVI/ESPHSA/FPAS2/ALEVA/SCACBA/SOP03C/SSADPC/STHPLG/SKTGRV/VLCUIR/RETIN2/TRSEV1/REPNTC/LVAVIP/LVAREI/SASURV/KTGREP/SGACHA/BEL01/APL03/FSTPO/ALOUC5/CMAR3P/FIPOU2/NA406/BVA7/ECLHB4/RDIF10/PNSTRD/ISOFIX/ENPH01/HRGM01/SANFLT/CSRGAC/SANACF/SDPCLV/TLRP00/SPRODI/SAN613/AVFAP/AIRBDE/CHC03/E06T/SAN806/SSPTLP/SANCML/SSFLEX/SDRQAR/SEXTIN/M2019/PHAS1/SPRTQT/SAN913/STHABT/SSTYAD/HYB01/SSCABA/SANBAT/VEC012/XJB1SU/SSNBT/H5H",
|
||||
"assets": [
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https: //3dv2.renault.com/ImageFromBookmark?configuration=ADR00%2FDLIGM2%2FPGPRT2%2FFEUAR3%2FCDVIT1%2FSSCCPC%2FRCALL%2FMET04%2FDANGMO%2FSSRCAR%2FAVGSI%2FITPK7%2FMLEXP1%2FSPERTA%2FSSPERG%2FSPERTP%2FVOLCHA%2FSREACT%2FDWGE01%2FAVCAM%2FHJB%2FEA3%2FESS%2FDG%2FTEMP%2FTR4X2%2FRVDIST%2FSBARTO%2FCA02%2FTOPAN%2FPBNCH%2FVSTLAR%2FCPE%2FRET04%2FRALU17%2FDRA%2FDRAP05%2FHARM01%2FBIXPE%2FKM%2FSSDECA%2FESPHSA%2FFPAS2%2FALEVA%2FSOP03C%2FSSADPC%2FVLCUIR%2FRETIN2%2FREPNTC%2FLVAVIP%2FLVAREI%2FSGACHA%2FALOUC5%2FNA406%2FBVA7%2FECLHB4%2FRDIF10%2FCSRGAC%2FSANACF%2FTLRP00%2FAIRBDE%2FCHC03%2FSSPTLP%2FSPRTQT%2FSAN913%2FHYB01%2FH5H&databaseId=3e814da7-766d-4039-ac69-f001a1f738c8&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https: //3dv2.renault.com/ImageFromBookmark?configuration=ADR00%2FDLIGM2%2FPGPRT2%2FFEUAR3%2FCDVIT1%2FSSCCPC%2FRCALL%2FMET04%2FDANGMO%2FSSRCAR%2FAVGSI%2FITPK7%2FMLEXP1%2FSPERTA%2FSSPERG%2FSPERTP%2FVOLCHA%2FSREACT%2FDWGE01%2FAVCAM%2FHJB%2FEA3%2FESS%2FDG%2FTEMP%2FTR4X2%2FRVDIST%2FSBARTO%2FCA02%2FTOPAN%2FPBNCH%2FVSTLAR%2FCPE%2FRET04%2FRALU17%2FDRA%2FDRAP05%2FHARM01%2FBIXPE%2FKM%2FSSDECA%2FESPHSA%2FFPAS2%2FALEVA%2FSOP03C%2FSSADPC%2FVLCUIR%2FRETIN2%2FREPNTC%2FLVAVIP%2FLVAREI%2FSGACHA%2FALOUC5%2FNA406%2FBVA7%2FECLHB4%2FRDIF10%2FCSRGAC%2FSANACF%2FTLRP00%2FAIRBDE%2FCHC03%2FSSPTLP%2FSPRTQT%2FSAN913%2FHYB01%2FH5H&databaseId=3e814da7-766d-4039-ac69-f001a1f738c8&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"yearsOfMaintenance": 12,
|
||||
"connectivityTechnology": "NONE",
|
||||
"easyConnectStore": false,
|
||||
"electrical": false,
|
||||
"rlinkStore": false,
|
||||
"deliveryDate": "2020-06-17",
|
||||
"retrievedFromDhs": false,
|
||||
"engineEnergyType": "OTHER",
|
||||
"radioCode": "1234"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -2,11 +2,15 @@
|
||||
|
||||
from collections.abc import Generator
|
||||
import datetime
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
from renault_api.kamereon.exceptions import QuotaLimitException
|
||||
from renault_api.kamereon.exceptions import (
|
||||
AccessDeniedException,
|
||||
NotSupportedException,
|
||||
QuotaLimitException,
|
||||
)
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -241,3 +245,89 @@ async def test_sensor_throttling_after_init(
|
||||
assert not hass.states.get(entity_id).attributes.get(ATTR_ASSUMED_STATE)
|
||||
assert "Renault API throttled" not in caplog.text
|
||||
assert "Renault hub currently throttled: scan skipped" not in caplog.text
|
||||
|
||||
|
||||
# scan interval in seconds = (3600 * num_calls) / MAX_CALLS_PER_HOURS
|
||||
# MAX_CALLS_PER_HOURS being a constant, for now 60 calls per hour
|
||||
# num_calls = num_coordinator_car_0 + num_coordinator_car_1 + ... + num_coordinator_car_n
|
||||
@pytest.mark.parametrize(
|
||||
("vehicle_type", "vehicle_count", "scan_interval"),
|
||||
[
|
||||
("zoe_40", 1, 300), # 5 coordinators => 5 minutes interval
|
||||
("captur_fuel", 1, 240), # 4 coordinators => 4 minutes interval
|
||||
("multi", 2, 540), # 9 coordinators => 9 minutes interval
|
||||
],
|
||||
indirect=["vehicle_type"],
|
||||
)
|
||||
async def test_dynamic_scan_interval(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
vehicle_count: int,
|
||||
scan_interval: int,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
fixtures_with_data: dict[str, AsyncMock],
|
||||
) -> None:
|
||||
"""Test scan interval."""
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count
|
||||
|
||||
# 2 seconds before the expected scan interval > not called
|
||||
freezer.tick(datetime.timedelta(seconds=scan_interval - 2))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count
|
||||
|
||||
# 2 seconds after the expected scan interval > called
|
||||
freezer.tick(datetime.timedelta(seconds=4))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count * 2
|
||||
|
||||
|
||||
# scan interval in seconds = (3600 * num_calls) / MAX_CALLS_PER_HOURS
|
||||
# MAX_CALLS_PER_HOURS being a constant, for now 60 calls per hour
|
||||
# num_calls = num_coordinator_car_0 + num_coordinator_car_1 + ... + num_coordinator_car_n
|
||||
@pytest.mark.parametrize(
|
||||
("vehicle_type", "vehicle_count", "scan_interval"),
|
||||
[
|
||||
("zoe_40", 1, 240), # (5-1) coordinators => 4 minutes interval
|
||||
("captur_fuel", 1, 180), # (4-1) coordinators => 3 minutes interval
|
||||
("multi", 2, 420), # (9-2) coordinators => 7 minutes interval
|
||||
],
|
||||
indirect=["vehicle_type"],
|
||||
)
|
||||
async def test_dynamic_scan_interval_failed_coordinator(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
vehicle_count: int,
|
||||
scan_interval: int,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
fixtures_with_data: dict[str, AsyncMock],
|
||||
) -> None:
|
||||
"""Test scan interval."""
|
||||
fixtures_with_data["battery_status"].side_effect = NotSupportedException(
|
||||
"err.tech.501",
|
||||
"This feature is not technically supported by this gateway",
|
||||
)
|
||||
fixtures_with_data["lock_status"].side_effect = AccessDeniedException(
|
||||
"err.func.403",
|
||||
"Access is denied for this resource",
|
||||
)
|
||||
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count
|
||||
|
||||
# 2 seconds before the expected scan interval > not called
|
||||
freezer.tick(datetime.timedelta(seconds=scan_interval - 2))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count
|
||||
|
||||
# 2 seconds after the expected scan interval > called
|
||||
freezer.tick(datetime.timedelta(seconds=4))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert fixtures_with_data["cockpit"].call_count == vehicle_count * 2
|
||||
|
Loading…
x
Reference in New Issue
Block a user