mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Fix evohome to gracefully handle null schedules (#140036)
* extend tests to catch null schedules * add fixture with null schedule * remove null schedules for now * fic the typing for _schedule attr (is list, not dict) * add valid schedule to fixture * update ssetpoints only if there is a schedule * snapshot to match last change * refactor: dont update switchpoints if no schedule * add in warnings for null schedules * add fixture for DHW without schedule
This commit is contained in:
parent
9a90e1e410
commit
c834944ee7
@ -207,10 +207,18 @@ class EvoDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
async def _update_v2_schedules(self) -> None:
|
async def _update_v2_schedules(self) -> None:
|
||||||
for zone in self.tcs.zones:
|
for zone in self.tcs.zones:
|
||||||
await zone.get_schedule()
|
try:
|
||||||
|
await zone.get_schedule()
|
||||||
|
except ec2.InvalidScheduleError as err:
|
||||||
|
self.logger.warning(
|
||||||
|
"Zone '%s' has an invalid/missing schedule: %r", zone.name, err
|
||||||
|
)
|
||||||
|
|
||||||
if dhw := self.tcs.hotwater:
|
if dhw := self.tcs.hotwater:
|
||||||
await dhw.get_schedule()
|
try:
|
||||||
|
await dhw.get_schedule()
|
||||||
|
except ec2.InvalidScheduleError as err:
|
||||||
|
self.logger.warning("DHW has an invalid/missing schedule: %r", err)
|
||||||
|
|
||||||
async def _async_update_data(self) -> EvoLocStatusResponseT: # type: ignore[override]
|
async def _async_update_data(self) -> EvoLocStatusResponseT: # type: ignore[override]
|
||||||
"""Fetch the latest state of an entire TCC Location.
|
"""Fetch the latest state of an entire TCC Location.
|
||||||
|
@ -6,6 +6,7 @@ import logging
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import evohomeasync2 as evo
|
import evohomeasync2 as evo
|
||||||
|
from evohomeasync2.schemas.typedefs import DayOfWeekDhwT
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
@ -102,7 +103,7 @@ class EvoChild(EvoEntity):
|
|||||||
|
|
||||||
self._evo_tcs = evo_device.tcs
|
self._evo_tcs = evo_device.tcs
|
||||||
|
|
||||||
self._schedule: dict[str, Any] | None = None
|
self._schedule: list[DayOfWeekDhwT] | None = None
|
||||||
self._setpoints: dict[str, Any] = {}
|
self._setpoints: dict[str, Any] = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -123,6 +124,9 @@ class EvoChild(EvoEntity):
|
|||||||
Only Zones & DHW controllers (but not the TCS) can have schedules.
|
Only Zones & DHW controllers (but not the TCS) can have schedules.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not self._schedule:
|
||||||
|
return self._setpoints
|
||||||
|
|
||||||
this_sp_dtm, this_sp_val = self._evo_device.this_switchpoint
|
this_sp_dtm, this_sp_val = self._evo_device.this_switchpoint
|
||||||
next_sp_dtm, next_sp_val = self._evo_device.next_switchpoint
|
next_sp_dtm, next_sp_val = self._evo_device.next_switchpoint
|
||||||
|
|
||||||
@ -152,10 +156,10 @@ class EvoChild(EvoEntity):
|
|||||||
self._evo_device,
|
self._evo_device,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
self._schedule = {}
|
self._schedule = []
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self._schedule = schedule or {} # mypy hint
|
self._schedule = schedule # type: ignore[assignment]
|
||||||
|
|
||||||
_LOGGER.debug("Schedule['%s'] = %s", self.name, schedule)
|
_LOGGER.debug("Schedule['%s'] = %s", self.name, schedule)
|
||||||
|
|
||||||
|
@ -48,18 +48,18 @@ def location_status_fixture(install: str, loc_id: str | None = None) -> JsonObje
|
|||||||
return load_json_object_fixture(f"{install}/status_{loc_id}.json", DOMAIN)
|
return load_json_object_fixture(f"{install}/status_{loc_id}.json", DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
def dhw_schedule_fixture(install: str) -> JsonObjectType:
|
def dhw_schedule_fixture(install: str, dhw_id: str | None = None) -> JsonObjectType:
|
||||||
"""Load JSON for the schedule of a domesticHotWater zone."""
|
"""Load JSON for the schedule of a domesticHotWater zone."""
|
||||||
try:
|
try:
|
||||||
return load_json_object_fixture(f"{install}/schedule_dhw.json", DOMAIN)
|
return load_json_object_fixture(f"{install}/schedule_{dhw_id}.json", DOMAIN)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return load_json_object_fixture("default/schedule_dhw.json", DOMAIN)
|
return load_json_object_fixture("default/schedule_dhw.json", DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
def zone_schedule_fixture(install: str) -> JsonObjectType:
|
def zone_schedule_fixture(install: str, zon_id: str | None = None) -> JsonObjectType:
|
||||||
"""Load JSON for the schedule of a temperatureZone zone."""
|
"""Load JSON for the schedule of a temperatureZone zone."""
|
||||||
try:
|
try:
|
||||||
return load_json_object_fixture(f"{install}/schedule_zone.json", DOMAIN)
|
return load_json_object_fixture(f"{install}/schedule_{zon_id}.json", DOMAIN)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return load_json_object_fixture("default/schedule_zone.json", DOMAIN)
|
return load_json_object_fixture("default/schedule_zone.json", DOMAIN)
|
||||||
|
|
||||||
@ -120,9 +120,9 @@ def mock_make_request(install: str) -> Callable:
|
|||||||
|
|
||||||
elif "schedule" in url:
|
elif "schedule" in url:
|
||||||
if url.startswith("domesticHotWater"): # /v2/domesticHotWater/{id}/schedule
|
if url.startswith("domesticHotWater"): # /v2/domesticHotWater/{id}/schedule
|
||||||
return dhw_schedule_fixture(install)
|
return dhw_schedule_fixture(install, url[16:23])
|
||||||
if url.startswith("temperatureZone"): # /v2/temperatureZone/{id}/schedule
|
if url.startswith("temperatureZone"): # /v2/temperatureZone/{id}/schedule
|
||||||
return zone_schedule_fixture(install)
|
return zone_schedule_fixture(install, url[16:23])
|
||||||
|
|
||||||
pytest.fail(f"Unexpected request: {HTTPMethod.GET} {url}")
|
pytest.fail(f"Unexpected request: {HTTPMethod.GET} {url}")
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@ TEST_INSTALLS: Final = (
|
|||||||
"default", # evohome: multi-zone, with DHW
|
"default", # evohome: multi-zone, with DHW
|
||||||
"h032585", # VisionProWifi: no preset modes for TCS, zoneId=systemId
|
"h032585", # VisionProWifi: no preset modes for TCS, zoneId=systemId
|
||||||
"h099625", # RoundThermostat
|
"h099625", # RoundThermostat
|
||||||
|
"h139906", # zone with null schedule
|
||||||
"sys_004", # RoundModulation
|
"sys_004", # RoundModulation
|
||||||
)
|
)
|
||||||
# "botched", # as default: but with activeFaults, ghost zones & unknown types
|
# "botched", # as default: but with activeFaults, ghost zones & unknown types
|
||||||
|
|
||||||
TEST_INSTALLS_WITH_DHW: Final = ("default",)
|
TEST_INSTALLS_WITH_DHW: Final = ("default", "botched")
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dailySchedules": []
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dailySchedules": []
|
||||||
|
}
|
143
tests/components/evohome/fixtures/h139906/schedule_3454855.json
Normal file
143
tests/components/evohome/fixtures/h139906/schedule_3454855.json
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"dailySchedules": [
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Monday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "05:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 20.0,
|
||||||
|
"timeOfDay": "08:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Tuesday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "05:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 20.0,
|
||||||
|
"timeOfDay": "08:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Wednesday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "05:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 20.0,
|
||||||
|
"timeOfDay": "08:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "12:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Thursday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "05:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 20.0,
|
||||||
|
"timeOfDay": "08:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Friday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "05:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 20.0,
|
||||||
|
"timeOfDay": "08:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Saturday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "07:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dayOfWeek": "Sunday",
|
||||||
|
"switchpoints": [
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.0,
|
||||||
|
"timeOfDay": "07:30:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 22.5,
|
||||||
|
"timeOfDay": "16:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heatSetpoint": 15.0,
|
||||||
|
"timeOfDay": "23:00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"locationId": "2727366",
|
||||||
|
"gateways": [
|
||||||
|
{
|
||||||
|
"gatewayId": "2513794",
|
||||||
|
"temperatureControlSystems": [
|
||||||
|
{
|
||||||
|
"systemId": "3454856",
|
||||||
|
"zones": [
|
||||||
|
{
|
||||||
|
"zoneId": "3454854",
|
||||||
|
"temperatureStatus": {
|
||||||
|
"temperature": 22.0,
|
||||||
|
"isAvailable": true
|
||||||
|
},
|
||||||
|
"activeFaults": [
|
||||||
|
{
|
||||||
|
"faultType": "TempZoneSensorCommunicationLost",
|
||||||
|
"since": "2025-02-06T11:20:29"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setpointStatus": {
|
||||||
|
"targetHeatTemperature": 5.0,
|
||||||
|
"setpointMode": "FollowSchedule"
|
||||||
|
},
|
||||||
|
"name": "Thermostat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"zoneId": "3454855",
|
||||||
|
"temperatureStatus": {
|
||||||
|
"temperature": 22.0,
|
||||||
|
"isAvailable": true
|
||||||
|
},
|
||||||
|
"activeFaults": [],
|
||||||
|
"setpointStatus": {
|
||||||
|
"targetHeatTemperature": 20.0,
|
||||||
|
"setpointMode": "FollowSchedule"
|
||||||
|
},
|
||||||
|
"name": "Thermostat 2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activeFaults": [],
|
||||||
|
"systemModeStatus": {
|
||||||
|
"mode": "Auto",
|
||||||
|
"isPermanent": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activeFaults": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
125
tests/components/evohome/fixtures/h139906/user_locations.json
Normal file
125
tests/components/evohome/fixtures/h139906/user_locations.json
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"locationInfo": {
|
||||||
|
"locationId": "2727366",
|
||||||
|
"name": "Vr**********",
|
||||||
|
"streetAddress": "********** *",
|
||||||
|
"city": "*********",
|
||||||
|
"country": "Netherlands",
|
||||||
|
"postcode": "******",
|
||||||
|
"locationType": "Residential",
|
||||||
|
"useDaylightSaveSwitching": true,
|
||||||
|
"timeZone": {
|
||||||
|
"timeZoneId": "WEuropeStandardTime",
|
||||||
|
"displayName": "(UTC+01:00) Amsterdam, Berlijn, Bern, Rome, Stockholm, Wenen",
|
||||||
|
"offsetMinutes": 60,
|
||||||
|
"currentOffsetMinutes": 60,
|
||||||
|
"supportsDaylightSaving": true
|
||||||
|
},
|
||||||
|
"locationOwner": {
|
||||||
|
"userId": "2276512",
|
||||||
|
"username": "nobody@nowhere.com",
|
||||||
|
"firstname": "Gl***",
|
||||||
|
"lastname": "de*****"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gateways": [
|
||||||
|
{
|
||||||
|
"gatewayInfo": {
|
||||||
|
"gatewayId": "2513794",
|
||||||
|
"mac": "************",
|
||||||
|
"crc": "****",
|
||||||
|
"isWiFi": false
|
||||||
|
},
|
||||||
|
"temperatureControlSystems": [
|
||||||
|
{
|
||||||
|
"systemId": "3454856",
|
||||||
|
"modelType": "EvoTouch",
|
||||||
|
"zones": [
|
||||||
|
{
|
||||||
|
"zoneId": "3454854",
|
||||||
|
"modelType": "HeatingZone",
|
||||||
|
"setpointCapabilities": {
|
||||||
|
"maxHeatSetpoint": 35.0,
|
||||||
|
"minHeatSetpoint": 5.0,
|
||||||
|
"valueResolution": 0.5,
|
||||||
|
"canControlHeat": true,
|
||||||
|
"canControlCool": false,
|
||||||
|
"allowedSetpointModes": [
|
||||||
|
"PermanentOverride",
|
||||||
|
"FollowSchedule",
|
||||||
|
"TemporaryOverride"
|
||||||
|
],
|
||||||
|
"maxDuration": "1.00:00:00",
|
||||||
|
"timingResolution": "00:10:00"
|
||||||
|
},
|
||||||
|
"scheduleCapabilities": {
|
||||||
|
"maxSwitchpointsPerDay": 6,
|
||||||
|
"minSwitchpointsPerDay": 1,
|
||||||
|
"timingResolution": "00:10:00",
|
||||||
|
"setpointValueResolution": 0.5
|
||||||
|
},
|
||||||
|
"name": "Thermostat",
|
||||||
|
"zoneType": "ZoneTemperatureControl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"zoneId": "3454855",
|
||||||
|
"modelType": "RoundWireless",
|
||||||
|
"setpointCapabilities": {
|
||||||
|
"maxHeatSetpoint": 35.0,
|
||||||
|
"minHeatSetpoint": 5.0,
|
||||||
|
"valueResolution": 0.5,
|
||||||
|
"canControlHeat": true,
|
||||||
|
"canControlCool": false,
|
||||||
|
"allowedSetpointModes": [
|
||||||
|
"PermanentOverride",
|
||||||
|
"FollowSchedule",
|
||||||
|
"TemporaryOverride"
|
||||||
|
],
|
||||||
|
"maxDuration": "1.00:00:00",
|
||||||
|
"timingResolution": "00:10:00"
|
||||||
|
},
|
||||||
|
"scheduleCapabilities": {
|
||||||
|
"maxSwitchpointsPerDay": 6,
|
||||||
|
"minSwitchpointsPerDay": 0,
|
||||||
|
"timingResolution": "00:10:00",
|
||||||
|
"setpointValueResolution": 0.5
|
||||||
|
},
|
||||||
|
"name": "Thermostat 2",
|
||||||
|
"zoneType": "Thermostat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"allowedSystemModes": [
|
||||||
|
{
|
||||||
|
"systemMode": "Auto",
|
||||||
|
"canBePermanent": true,
|
||||||
|
"canBeTemporary": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemMode": "AutoWithEco",
|
||||||
|
"canBePermanent": true,
|
||||||
|
"canBeTemporary": true,
|
||||||
|
"maxDuration": "1.00:00:00",
|
||||||
|
"timingResolution": "01:00:00",
|
||||||
|
"timingMode": "Duration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemMode": "Away",
|
||||||
|
"canBePermanent": true,
|
||||||
|
"canBeTemporary": true,
|
||||||
|
"maxDuration": "99.00:00:00",
|
||||||
|
"timingResolution": "1.00:00:00",
|
||||||
|
"timingMode": "Period"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemMode": "HeatingOff",
|
||||||
|
"canBePermanent": true,
|
||||||
|
"canBeTemporary": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -29,6 +29,16 @@
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_ctl_set_hvac_mode[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
<SystemMode.HEATING_OFF: 'HeatingOff'>,
|
||||||
|
),
|
||||||
|
tuple(
|
||||||
|
<SystemMode.AUTO: 'Auto'>,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_ctl_set_hvac_mode[minimal]
|
# name: test_ctl_set_hvac_mode[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
@ -70,6 +80,13 @@
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_ctl_turn_off[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
<SystemMode.HEATING_OFF: 'HeatingOff'>,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_ctl_turn_off[minimal]
|
# name: test_ctl_turn_off[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
@ -105,6 +122,13 @@
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_ctl_turn_on[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
<SystemMode.AUTO: 'Auto'>,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_ctl_turn_on[minimal]
|
# name: test_ctl_turn_on[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
@ -1118,6 +1142,136 @@
|
|||||||
'state': 'heat',
|
'state': 'heat',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_setup_platform[h139906][climate.thermostat-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'current_temperature': 22.0,
|
||||||
|
'friendly_name': 'Thermostat',
|
||||||
|
'hvac_modes': list([
|
||||||
|
<HVACMode.OFF: 'off'>,
|
||||||
|
<HVACMode.HEAT: 'heat'>,
|
||||||
|
]),
|
||||||
|
'max_temp': 35.0,
|
||||||
|
'min_temp': 5.0,
|
||||||
|
'preset_mode': 'none',
|
||||||
|
'preset_modes': list([
|
||||||
|
'none',
|
||||||
|
'temporary',
|
||||||
|
'permanent',
|
||||||
|
]),
|
||||||
|
'status': dict({
|
||||||
|
'activeFaults': tuple(
|
||||||
|
dict({
|
||||||
|
'fault_type': 'TempZoneSensorCommunicationLost',
|
||||||
|
'since': '2025-02-06T11:20:29+01:00',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
'setpoint_status': dict({
|
||||||
|
'setpoint_mode': 'FollowSchedule',
|
||||||
|
'target_heat_temperature': 5.0,
|
||||||
|
}),
|
||||||
|
'setpoints': dict({
|
||||||
|
}),
|
||||||
|
'temperature_status': dict({
|
||||||
|
'is_available': True,
|
||||||
|
'temperature': 22.0,
|
||||||
|
}),
|
||||||
|
'zone_id': '3454854',
|
||||||
|
}),
|
||||||
|
'supported_features': <ClimateEntityFeature: 401>,
|
||||||
|
'temperature': 5.0,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'climate.thermostat',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'off',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_setup_platform[h139906][climate.thermostat_2-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'current_temperature': 22.0,
|
||||||
|
'friendly_name': 'Thermostat 2',
|
||||||
|
'hvac_modes': list([
|
||||||
|
<HVACMode.OFF: 'off'>,
|
||||||
|
<HVACMode.HEAT: 'heat'>,
|
||||||
|
]),
|
||||||
|
'max_temp': 35.0,
|
||||||
|
'min_temp': 5.0,
|
||||||
|
'preset_mode': 'none',
|
||||||
|
'preset_modes': list([
|
||||||
|
'none',
|
||||||
|
'temporary',
|
||||||
|
'permanent',
|
||||||
|
]),
|
||||||
|
'status': dict({
|
||||||
|
'activeFaults': tuple(
|
||||||
|
),
|
||||||
|
'setpoint_status': dict({
|
||||||
|
'setpoint_mode': 'FollowSchedule',
|
||||||
|
'target_heat_temperature': 20.0,
|
||||||
|
}),
|
||||||
|
'setpoints': dict({
|
||||||
|
'next_sp_from': HAFakeDatetime(2024, 7, 10, 23, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin')),
|
||||||
|
'next_sp_temp': 15.0,
|
||||||
|
'this_sp_from': HAFakeDatetime(2024, 7, 10, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin')),
|
||||||
|
'this_sp_temp': 22.5,
|
||||||
|
}),
|
||||||
|
'temperature_status': dict({
|
||||||
|
'is_available': True,
|
||||||
|
'temperature': 22.0,
|
||||||
|
}),
|
||||||
|
'zone_id': '3454855',
|
||||||
|
}),
|
||||||
|
'supported_features': <ClimateEntityFeature: 401>,
|
||||||
|
'temperature': 20.0,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'climate.thermostat_2',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'heat',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_setup_platform[h139906][climate.vr-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'current_temperature': 22.0,
|
||||||
|
'friendly_name': 'Vr**********',
|
||||||
|
'hvac_modes': list([
|
||||||
|
<HVACMode.OFF: 'off'>,
|
||||||
|
<HVACMode.HEAT: 'heat'>,
|
||||||
|
]),
|
||||||
|
'icon': 'mdi:thermostat',
|
||||||
|
'max_temp': 35,
|
||||||
|
'min_temp': 7,
|
||||||
|
'preset_mode': None,
|
||||||
|
'preset_modes': list([
|
||||||
|
'eco',
|
||||||
|
'away',
|
||||||
|
]),
|
||||||
|
'status': dict({
|
||||||
|
'activeSystemFaults': tuple(
|
||||||
|
),
|
||||||
|
'system_id': '3454856',
|
||||||
|
'system_mode_status': dict({
|
||||||
|
'is_permanent': True,
|
||||||
|
'mode': 'Auto',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'supported_features': <ClimateEntityFeature: 400>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'climate.vr',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'heat',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_setup_platform[minimal][climate.main_room-state]
|
# name: test_setup_platform[minimal][climate.main_room-state]
|
||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
@ -1312,6 +1466,13 @@
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_zone_set_hvac_mode[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
5.0,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_zone_set_hvac_mode[minimal]
|
# name: test_zone_set_hvac_mode[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
@ -1365,6 +1526,19 @@
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_zone_set_preset_mode[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
5.0,
|
||||||
|
),
|
||||||
|
tuple(
|
||||||
|
5.0,
|
||||||
|
),
|
||||||
|
dict({
|
||||||
|
'until': None,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_zone_set_preset_mode[minimal]
|
# name: test_zone_set_preset_mode[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
@ -1412,6 +1586,13 @@
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_zone_set_temperature[h139906]
|
||||||
|
list([
|
||||||
|
dict({
|
||||||
|
'until': None,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_zone_set_temperature[minimal]
|
# name: test_zone_set_temperature[minimal]
|
||||||
list([
|
list([
|
||||||
dict({
|
dict({
|
||||||
@ -1447,6 +1628,13 @@
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_zone_turn_off[h139906]
|
||||||
|
list([
|
||||||
|
tuple(
|
||||||
|
5.0,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_zone_turn_off[minimal]
|
# name: test_zone_turn_off[minimal]
|
||||||
list([
|
list([
|
||||||
tuple(
|
tuple(
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
# name: test_setup[h099625]
|
# name: test_setup[h099625]
|
||||||
dict_keys(['refresh_system', 'set_system_mode', 'clear_zone_override', 'set_zone_override'])
|
dict_keys(['refresh_system', 'set_system_mode', 'clear_zone_override', 'set_zone_override'])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_setup[h139906]
|
||||||
|
dict_keys(['refresh_system', 'set_system_mode', 'clear_zone_override', 'set_zone_override'])
|
||||||
|
# ---
|
||||||
# name: test_setup[minimal]
|
# name: test_setup[minimal]
|
||||||
dict_keys(['refresh_system', 'reset_system', 'set_system_mode', 'clear_zone_override', 'set_zone_override'])
|
dict_keys(['refresh_system', 'reset_system', 'set_system_mode', 'clear_zone_override', 'set_zone_override'])
|
||||||
# ---
|
# ---
|
||||||
|
@ -1,4 +1,14 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
|
# name: test_set_operation_mode[botched]
|
||||||
|
list([
|
||||||
|
dict({
|
||||||
|
'until': HAFakeDatetime(2024, 7, 10, 12, 0, tzinfo=datetime.timezone.utc),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'until': HAFakeDatetime(2024, 7, 10, 12, 0, tzinfo=datetime.timezone.utc),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
# ---
|
||||||
# name: test_set_operation_mode[default]
|
# name: test_set_operation_mode[default]
|
||||||
list([
|
list([
|
||||||
dict({
|
dict({
|
||||||
|
@ -33,7 +33,7 @@ from .const import TEST_INSTALLS_WITH_DHW
|
|||||||
DHW_ENTITY_ID = "water_heater.domestic_hot_water"
|
DHW_ENTITY_ID = "water_heater.domestic_hot_water"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("install", [*TEST_INSTALLS_WITH_DHW, "botched"])
|
@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
|
||||||
async def test_setup_platform(
|
async def test_setup_platform(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: dict[str, str],
|
config: dict[str, str],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user