Enforce a minimum temperature range for nest thermostats (#98238)

This commit is contained in:
Allen Porter 2023-08-11 03:21:19 -07:00 committed by GitHub
parent b67e290eaa
commit a0ac8ba5a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 0 deletions

View file

@ -75,6 +75,7 @@ FAN_INV_MODES = list(FAN_INV_MODE_MAP)
MAX_FAN_DURATION = 43200 # 15 hours is the max in the SDM API
MIN_TEMP = 10
MAX_TEMP = 32
MIN_TEMP_RANGE = 1.66667
async def async_setup_entry(
@ -313,6 +314,13 @@ class ThermostatEntity(ClimateEntity):
try:
if self.preset_mode == PRESET_ECO or hvac_mode == HVACMode.HEAT_COOL:
if low_temp and high_temp:
if high_temp - low_temp < MIN_TEMP_RANGE:
# Ensure there is a minimum gap from the new temp. Pick
# the temp that is not changing as the one to move.
if abs(high_temp - self.target_temperature_high) < 0.01:
high_temp = low_temp + MIN_TEMP_RANGE
else:
low_temp = high_temp - MIN_TEMP_RANGE
await trait.set_range(low_temp, high_temp)
elif hvac_mode == HVACMode.COOL and temp:
await trait.set_cool(temp)

View file

@ -758,6 +758,75 @@ async def test_thermostat_set_temperature_hvac_mode(
}
@pytest.mark.parametrize(
("setpoint", "target_low", "target_high", "expected_params"),
[
(
{
"heatCelsius": 19.0,
"coolCelsius": 25.0,
},
19.0,
20.0,
# Cool is accepted and lowers heat by the min range
{"heatCelsius": 18.33333, "coolCelsius": 20.0},
),
(
{
"heatCelsius": 19.0,
"coolCelsius": 25.0,
},
24.0,
25.0,
# Cool is accepted and lowers heat by the min range
{"heatCelsius": 24.0, "coolCelsius": 25.66667},
),
],
)
async def test_thermostat_set_temperature_range_too_close(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
setpoint: dict[str, Any],
target_low: float,
target_high: float,
expected_params: dict[str, Any],
) -> None:
"""Test setting an HVAC temperature range that is too small of a range."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": setpoint,
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
# Move the target temp to be in too small of a range
await common.async_set_temperature(
hass,
target_temp_low=target_low,
target_temp_high=target_high,
)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetRange",
"params": expected_params,
}
async def test_thermostat_set_heat_cool(
hass: HomeAssistant,
setup_platform: PlatformSetup,