mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Add climate platform to Mazda integration (#75037)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
7ef145d4ce
commit
f5c56152d5
@ -33,13 +33,14 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
UpdateFailed,
|
UpdateFailed,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .const import DATA_CLIENT, DATA_COORDINATOR, DATA_VEHICLES, DOMAIN
|
from .const import DATA_CLIENT, DATA_COORDINATOR, DATA_REGION, DATA_VEHICLES, DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
Platform.BUTTON,
|
Platform.BUTTON,
|
||||||
|
Platform.CLIMATE,
|
||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
@ -161,6 +162,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
vehicle["evStatus"] = await with_timeout(
|
vehicle["evStatus"] = await with_timeout(
|
||||||
mazda_client.get_ev_vehicle_status(vehicle["id"])
|
mazda_client.get_ev_vehicle_status(vehicle["id"])
|
||||||
)
|
)
|
||||||
|
vehicle["hvacSetting"] = await with_timeout(
|
||||||
|
mazda_client.get_hvac_setting(vehicle["id"])
|
||||||
|
)
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id][DATA_VEHICLES] = vehicles
|
hass.data[DOMAIN][entry.entry_id][DATA_VEHICLES] = vehicles
|
||||||
|
|
||||||
@ -185,6 +189,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
DATA_CLIENT: mazda_client,
|
DATA_CLIENT: mazda_client,
|
||||||
DATA_COORDINATOR: coordinator,
|
DATA_COORDINATOR: coordinator,
|
||||||
|
DATA_REGION: region,
|
||||||
DATA_VEHICLES: [],
|
DATA_VEHICLES: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
187
homeassistant/components/mazda/climate.py
Normal file
187
homeassistant/components/mazda/climate.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
"""Platform for Mazda climate integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pymazda import Client as MazdaAPIClient
|
||||||
|
|
||||||
|
from homeassistant.components.climate import (
|
||||||
|
ClimateEntity,
|
||||||
|
ClimateEntityFeature,
|
||||||
|
HVACMode,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_TEMPERATURE,
|
||||||
|
PRECISION_HALVES,
|
||||||
|
PRECISION_WHOLE,
|
||||||
|
UnitOfTemperature,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
from homeassistant.util.temperature import convert as convert_temperature
|
||||||
|
|
||||||
|
from . import MazdaEntity
|
||||||
|
from .const import DATA_CLIENT, DATA_COORDINATOR, DATA_REGION, DOMAIN
|
||||||
|
|
||||||
|
PRESET_DEFROSTER_OFF = "Defroster Off"
|
||||||
|
PRESET_DEFROSTER_FRONT = "Front Defroster"
|
||||||
|
PRESET_DEFROSTER_REAR = "Rear Defroster"
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR = "Front and Rear Defroster"
|
||||||
|
|
||||||
|
|
||||||
|
def _front_defroster_enabled(preset_mode: str | None) -> bool:
|
||||||
|
return preset_mode in [
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
PRESET_DEFROSTER_FRONT,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _rear_defroster_enabled(preset_mode: str | None) -> bool:
|
||||||
|
return preset_mode in [
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
PRESET_DEFROSTER_REAR,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the climate platform."""
|
||||||
|
entry_data = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
client = entry_data[DATA_CLIENT]
|
||||||
|
coordinator = entry_data[DATA_COORDINATOR]
|
||||||
|
region = entry_data[DATA_REGION]
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
MazdaClimateEntity(client, coordinator, index, region)
|
||||||
|
for index, data in enumerate(coordinator.data)
|
||||||
|
if data["isElectric"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MazdaClimateEntity(MazdaEntity, ClimateEntity):
|
||||||
|
"""Class for a Mazda climate entity."""
|
||||||
|
|
||||||
|
_attr_name = "Climate"
|
||||||
|
_attr_supported_features = (
|
||||||
|
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
|
||||||
|
)
|
||||||
|
_attr_hvac_modes = [HVACMode.HEAT_COOL, HVACMode.OFF]
|
||||||
|
_attr_preset_modes = [
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
PRESET_DEFROSTER_FRONT,
|
||||||
|
PRESET_DEFROSTER_REAR,
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
client: MazdaAPIClient,
|
||||||
|
coordinator: DataUpdateCoordinator,
|
||||||
|
index: int,
|
||||||
|
region: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize Mazda climate entity."""
|
||||||
|
super().__init__(client, coordinator, index)
|
||||||
|
|
||||||
|
self.region = region
|
||||||
|
self._attr_unique_id = self.vin
|
||||||
|
|
||||||
|
if self.data["hvacSetting"]["temperatureUnit"] == "F":
|
||||||
|
self._attr_precision = PRECISION_WHOLE
|
||||||
|
self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
|
||||||
|
self._attr_min_temp = 61.0
|
||||||
|
self._attr_max_temp = 83.0
|
||||||
|
else:
|
||||||
|
self._attr_precision = PRECISION_HALVES
|
||||||
|
self._attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||||
|
if region == "MJO":
|
||||||
|
self._attr_min_temp = 18.5
|
||||||
|
self._attr_max_temp = 31.5
|
||||||
|
else:
|
||||||
|
self._attr_min_temp = 15.5
|
||||||
|
self._attr_max_temp = 28.5
|
||||||
|
|
||||||
|
self._update_state_attributes()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle_coordinator_update(self) -> None:
|
||||||
|
"""Update attributes when the coordinator data updates."""
|
||||||
|
self._update_state_attributes()
|
||||||
|
|
||||||
|
super()._handle_coordinator_update()
|
||||||
|
|
||||||
|
def _update_state_attributes(self) -> None:
|
||||||
|
# Update the HVAC mode
|
||||||
|
hvac_on = self.client.get_assumed_hvac_mode(self.vehicle_id)
|
||||||
|
self._attr_hvac_mode = HVACMode.HEAT_COOL if hvac_on else HVACMode.OFF
|
||||||
|
|
||||||
|
# Update the target temperature
|
||||||
|
hvac_setting = self.client.get_assumed_hvac_setting(self.vehicle_id)
|
||||||
|
self._attr_target_temperature = hvac_setting.get("temperature")
|
||||||
|
|
||||||
|
# Update the current temperature
|
||||||
|
current_temperature_celsius = self.data["evStatus"]["hvacInfo"][
|
||||||
|
"interiorTemperatureCelsius"
|
||||||
|
]
|
||||||
|
if self.data["hvacSetting"]["temperatureUnit"] == "F":
|
||||||
|
self._attr_current_temperature = convert_temperature(
|
||||||
|
current_temperature_celsius,
|
||||||
|
UnitOfTemperature.CELSIUS,
|
||||||
|
UnitOfTemperature.FAHRENHEIT,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._attr_current_temperature = current_temperature_celsius
|
||||||
|
|
||||||
|
# Update the preset mode based on the state of the front and rear defrosters
|
||||||
|
front_defroster = hvac_setting.get("frontDefroster")
|
||||||
|
rear_defroster = hvac_setting.get("rearDefroster")
|
||||||
|
if front_defroster and rear_defroster:
|
||||||
|
self._attr_preset_mode = PRESET_DEFROSTER_FRONT_AND_REAR
|
||||||
|
elif front_defroster:
|
||||||
|
self._attr_preset_mode = PRESET_DEFROSTER_FRONT
|
||||||
|
elif rear_defroster:
|
||||||
|
self._attr_preset_mode = PRESET_DEFROSTER_REAR
|
||||||
|
else:
|
||||||
|
self._attr_preset_mode = PRESET_DEFROSTER_OFF
|
||||||
|
|
||||||
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
|
"""Set a new HVAC mode."""
|
||||||
|
if hvac_mode == HVACMode.HEAT_COOL:
|
||||||
|
await self.client.turn_on_hvac(self.vehicle_id)
|
||||||
|
elif hvac_mode == HVACMode.OFF:
|
||||||
|
await self.client.turn_off_hvac(self.vehicle_id)
|
||||||
|
|
||||||
|
self._handle_coordinator_update()
|
||||||
|
|
||||||
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||||
|
"""Set a new target temperature."""
|
||||||
|
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is not None:
|
||||||
|
precision = self.precision
|
||||||
|
rounded_temperature = round(temperature / precision) * precision
|
||||||
|
|
||||||
|
await self.client.set_hvac_setting(
|
||||||
|
self.vehicle_id,
|
||||||
|
rounded_temperature,
|
||||||
|
self.data["hvacSetting"]["temperatureUnit"],
|
||||||
|
_front_defroster_enabled(self._attr_preset_mode),
|
||||||
|
_rear_defroster_enabled(self._attr_preset_mode),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._handle_coordinator_update()
|
||||||
|
|
||||||
|
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||||
|
"""Turn on/off the front/rear defrosters according to the chosen preset mode."""
|
||||||
|
await self.client.set_hvac_setting(
|
||||||
|
self.vehicle_id,
|
||||||
|
self._attr_target_temperature,
|
||||||
|
self.data["hvacSetting"]["temperatureUnit"],
|
||||||
|
_front_defroster_enabled(preset_mode),
|
||||||
|
_rear_defroster_enabled(preset_mode),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._handle_coordinator_update()
|
@ -4,6 +4,7 @@ DOMAIN = "mazda"
|
|||||||
|
|
||||||
DATA_CLIENT = "mazda_client"
|
DATA_CLIENT = "mazda_client"
|
||||||
DATA_COORDINATOR = "coordinator"
|
DATA_COORDINATOR = "coordinator"
|
||||||
|
DATA_REGION = "region"
|
||||||
DATA_VEHICLES = "vehicles"
|
DATA_VEHICLES = "vehicles"
|
||||||
|
|
||||||
MAZDA_REGIONS = {"MNAO": "North America", "MME": "Europe", "MJO": "Japan"}
|
MAZDA_REGIONS = {"MNAO": "North America", "MME": "Europe", "MJO": "Japan"}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Tests for the Mazda Connected Services integration."""
|
"""Tests for the Mazda Connected Services integration."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||||
|
|
||||||
from pymazda import Client as MazdaAPI
|
from pymazda import Client as MazdaAPI
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ async def init_integration(
|
|||||||
get_ev_vehicle_status_fixture = json.loads(
|
get_ev_vehicle_status_fixture = json.loads(
|
||||||
load_fixture("mazda/get_ev_vehicle_status.json")
|
load_fixture("mazda/get_ev_vehicle_status.json")
|
||||||
)
|
)
|
||||||
|
get_hvac_setting_fixture = json.loads(load_fixture("mazda/get_hvac_setting.json"))
|
||||||
|
|
||||||
config_entry = MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT)
|
config_entry = MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT)
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
@ -61,6 +62,13 @@ async def init_integration(
|
|||||||
client_mock.stop_engine = AsyncMock()
|
client_mock.stop_engine = AsyncMock()
|
||||||
client_mock.turn_off_hazard_lights = AsyncMock()
|
client_mock.turn_off_hazard_lights = AsyncMock()
|
||||||
client_mock.turn_on_hazard_lights = AsyncMock()
|
client_mock.turn_on_hazard_lights = AsyncMock()
|
||||||
|
client_mock.refresh_vehicle_status = AsyncMock()
|
||||||
|
client_mock.get_hvac_setting = AsyncMock(return_value=get_hvac_setting_fixture)
|
||||||
|
client_mock.get_assumed_hvac_setting = Mock(return_value=get_hvac_setting_fixture)
|
||||||
|
client_mock.get_assumed_hvac_mode = Mock(return_value=True)
|
||||||
|
client_mock.set_hvac_setting = AsyncMock()
|
||||||
|
client_mock.turn_on_hvac = AsyncMock()
|
||||||
|
client_mock.turn_off_hvac = AsyncMock()
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.mazda.config_flow.MazdaAPI",
|
"homeassistant.components.mazda.config_flow.MazdaAPI",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"chargeInfo": {
|
|
||||||
"lastUpdatedTimestamp": "20210807083956",
|
"lastUpdatedTimestamp": "20210807083956",
|
||||||
|
"chargeInfo": {
|
||||||
"batteryLevelPercentage": 80,
|
"batteryLevelPercentage": 80,
|
||||||
"drivingRangeKm": 218,
|
"drivingRangeKm": 218,
|
||||||
"pluggedIn": true,
|
"pluggedIn": true,
|
||||||
|
6
tests/components/mazda/fixtures/get_hvac_setting.json
Normal file
6
tests/components/mazda/fixtures/get_hvac_setting.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"temperature": 20,
|
||||||
|
"temperatureUnit": "C",
|
||||||
|
"frontDefroster": true,
|
||||||
|
"rearDefroster": false
|
||||||
|
}
|
327
tests/components/mazda/test_climate.py
Normal file
327
tests/components/mazda/test_climate.py
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
"""The climate tests for the Mazda Connected Services integration."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.climate import (
|
||||||
|
ATTR_HVAC_MODE,
|
||||||
|
ATTR_PRESET_MODE,
|
||||||
|
DOMAIN as CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_HVAC_MODE,
|
||||||
|
SERVICE_SET_PRESET_MODE,
|
||||||
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
)
|
||||||
|
from homeassistant.components.climate.const import (
|
||||||
|
ATTR_CURRENT_TEMPERATURE,
|
||||||
|
ATTR_HVAC_MODES,
|
||||||
|
ATTR_MAX_TEMP,
|
||||||
|
ATTR_MIN_TEMP,
|
||||||
|
ATTR_PRESET_MODES,
|
||||||
|
ClimateEntityFeature,
|
||||||
|
HVACMode,
|
||||||
|
)
|
||||||
|
from homeassistant.components.mazda.climate import (
|
||||||
|
PRESET_DEFROSTER_FRONT,
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
PRESET_DEFROSTER_REAR,
|
||||||
|
)
|
||||||
|
from homeassistant.components.mazda.const import DOMAIN
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
|
ATTR_FRIENDLY_NAME,
|
||||||
|
ATTR_SUPPORTED_FEATURES,
|
||||||
|
ATTR_TEMPERATURE,
|
||||||
|
CONF_EMAIL,
|
||||||
|
CONF_PASSWORD,
|
||||||
|
CONF_REGION,
|
||||||
|
UnitOfTemperature,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||||
|
|
||||||
|
from . import init_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, load_fixture
|
||||||
|
|
||||||
|
|
||||||
|
async def test_climate_setup(hass):
|
||||||
|
"""Test the setup of the climate entity."""
|
||||||
|
await init_integration(hass, electric_vehicle=True)
|
||||||
|
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
entry = entity_registry.async_get("climate.my_mazda3_climate")
|
||||||
|
assert entry
|
||||||
|
assert entry.unique_id == "JM000000000000000"
|
||||||
|
|
||||||
|
state = hass.states.get("climate.my_mazda3_climate")
|
||||||
|
assert state
|
||||||
|
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "My Mazda3 Climate"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"region, hvac_on, target_temperature, temperature_unit, front_defroster, rear_defroster, current_temperature_celsius, expected_hvac_mode, expected_preset_mode, expected_min_temp, expected_max_temp",
|
||||||
|
[
|
||||||
|
# Test with HVAC off
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
False,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
15.5,
|
||||||
|
28.5,
|
||||||
|
),
|
||||||
|
# Test with HVAC on
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
True,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
22,
|
||||||
|
HVACMode.HEAT_COOL,
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
15.5,
|
||||||
|
28.5,
|
||||||
|
),
|
||||||
|
# Test with front defroster on
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
False,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_FRONT,
|
||||||
|
15.5,
|
||||||
|
28.5,
|
||||||
|
),
|
||||||
|
# Test with rear defroster on
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
False,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_REAR,
|
||||||
|
15.5,
|
||||||
|
28.5,
|
||||||
|
),
|
||||||
|
# Test with front and rear defrosters on
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
False,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
True,
|
||||||
|
True,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
15.5,
|
||||||
|
28.5,
|
||||||
|
),
|
||||||
|
# Test with temperature unit F
|
||||||
|
(
|
||||||
|
"MNAO",
|
||||||
|
False,
|
||||||
|
70,
|
||||||
|
"F",
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
61.0,
|
||||||
|
83.0,
|
||||||
|
),
|
||||||
|
# Test with Japan region (uses different min/max temp settings)
|
||||||
|
(
|
||||||
|
"MJO",
|
||||||
|
False,
|
||||||
|
20,
|
||||||
|
"C",
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
22,
|
||||||
|
HVACMode.OFF,
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
18.5,
|
||||||
|
31.5,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_climate_state(
|
||||||
|
hass,
|
||||||
|
region,
|
||||||
|
hvac_on,
|
||||||
|
target_temperature,
|
||||||
|
temperature_unit,
|
||||||
|
front_defroster,
|
||||||
|
rear_defroster,
|
||||||
|
current_temperature_celsius,
|
||||||
|
expected_hvac_mode,
|
||||||
|
expected_preset_mode,
|
||||||
|
expected_min_temp,
|
||||||
|
expected_max_temp,
|
||||||
|
):
|
||||||
|
"""Test getting the state of the climate entity."""
|
||||||
|
if temperature_unit == "F":
|
||||||
|
hass.config.units = US_CUSTOMARY_SYSTEM
|
||||||
|
|
||||||
|
get_vehicles_fixture = json.loads(load_fixture("mazda/get_vehicles.json"))
|
||||||
|
get_vehicles_fixture[0]["isElectric"] = True
|
||||||
|
get_vehicle_status_fixture = json.loads(
|
||||||
|
load_fixture("mazda/get_vehicle_status.json")
|
||||||
|
)
|
||||||
|
get_ev_vehicle_status_fixture = json.loads(
|
||||||
|
load_fixture("mazda/get_ev_vehicle_status.json")
|
||||||
|
)
|
||||||
|
get_ev_vehicle_status_fixture["hvacInfo"][
|
||||||
|
"interiorTemperatureCelsius"
|
||||||
|
] = current_temperature_celsius
|
||||||
|
get_hvac_setting_fixture = {
|
||||||
|
"temperature": target_temperature,
|
||||||
|
"temperatureUnit": temperature_unit,
|
||||||
|
"frontDefroster": front_defroster,
|
||||||
|
"rearDefroster": rear_defroster,
|
||||||
|
}
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.validate_credentials",
|
||||||
|
return_value=True,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_vehicles",
|
||||||
|
return_value=get_vehicles_fixture,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_vehicle_status",
|
||||||
|
return_value=get_vehicle_status_fixture,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_ev_vehicle_status",
|
||||||
|
return_value=get_ev_vehicle_status_fixture,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_assumed_hvac_mode",
|
||||||
|
return_value=hvac_on,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_assumed_hvac_setting",
|
||||||
|
return_value=get_hvac_setting_fixture,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.mazda.MazdaAPI.get_hvac_setting",
|
||||||
|
return_value=get_hvac_setting_fixture,
|
||||||
|
):
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
CONF_EMAIL: "example@example.com",
|
||||||
|
CONF_PASSWORD: "password",
|
||||||
|
CONF_REGION: region,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("climate.my_mazda3_climate")
|
||||||
|
assert state
|
||||||
|
assert state.state == expected_hvac_mode
|
||||||
|
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "My Mazda3 Climate"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_SUPPORTED_FEATURES)
|
||||||
|
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
|
||||||
|
)
|
||||||
|
assert state.attributes.get(ATTR_HVAC_MODES) == [HVACMode.HEAT_COOL, HVACMode.OFF]
|
||||||
|
assert state.attributes.get(ATTR_PRESET_MODES) == [
|
||||||
|
PRESET_DEFROSTER_OFF,
|
||||||
|
PRESET_DEFROSTER_FRONT,
|
||||||
|
PRESET_DEFROSTER_REAR,
|
||||||
|
PRESET_DEFROSTER_FRONT_AND_REAR,
|
||||||
|
]
|
||||||
|
assert state.attributes.get(ATTR_MIN_TEMP) == expected_min_temp
|
||||||
|
assert state.attributes.get(ATTR_MAX_TEMP) == expected_max_temp
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) == round(
|
||||||
|
hass.config.units.temperature(
|
||||||
|
current_temperature_celsius, UnitOfTemperature.CELSIUS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert state.attributes.get(ATTR_TEMPERATURE) == target_temperature
|
||||||
|
assert state.attributes.get(ATTR_PRESET_MODE) == expected_preset_mode
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"hvac_mode, api_method",
|
||||||
|
[
|
||||||
|
(HVACMode.HEAT_COOL, "turn_on_hvac"),
|
||||||
|
(HVACMode.OFF, "turn_off_hvac"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_set_hvac_mode(hass, hvac_mode, api_method):
|
||||||
|
"""Test turning on and off the HVAC system."""
|
||||||
|
client_mock = await init_integration(hass, electric_vehicle=True)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_HVAC_MODE,
|
||||||
|
{ATTR_ENTITY_ID: "climate.my_mazda3_climate", ATTR_HVAC_MODE: hvac_mode},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
getattr(client_mock, api_method).assert_called_once_with(12345)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_target_temperature(hass):
|
||||||
|
"""Test setting the target temperature of the climate entity."""
|
||||||
|
client_mock = await init_integration(hass, electric_vehicle=True)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
{ATTR_ENTITY_ID: "climate.my_mazda3_climate", ATTR_TEMPERATURE: 22},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
client_mock.set_hvac_setting.assert_called_once_with(12345, 22, "C", True, False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"preset_mode, front_defroster, rear_defroster",
|
||||||
|
[
|
||||||
|
(PRESET_DEFROSTER_OFF, False, False),
|
||||||
|
(PRESET_DEFROSTER_FRONT, True, False),
|
||||||
|
(PRESET_DEFROSTER_REAR, False, True),
|
||||||
|
(PRESET_DEFROSTER_FRONT_AND_REAR, True, True),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_set_preset_mode(hass, preset_mode, front_defroster, rear_defroster):
|
||||||
|
"""Test turning on and off the front and rear defrosters."""
|
||||||
|
client_mock = await init_integration(hass, electric_vehicle=True)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_PRESET_MODE,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: "climate.my_mazda3_climate",
|
||||||
|
ATTR_PRESET_MODE: preset_mode,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
client_mock.set_hvac_setting.assert_called_once_with(
|
||||||
|
12345, 20, "C", front_defroster, rear_defroster
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user